You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity跳跃跑酷游戏Player与Camera更新方法卡顿问题求助

跑酷游戏Update/FixedUpdate/LateUpdate分工与卡顿修复

核心规则(解决卡顿的关键)

  • FixedUpdate:仅处理物理相关操作(如Rigidbody2D属性修改、物理碰撞检测),调用频率由物理时间步(默认0.02秒/次)控制,保证物理模拟稳定。
  • Update:处理输入检测、状态判断、动画控制,和渲染帧率同步,确保输入响应与动画流畅。
  • LateUpdate:处理依赖其他物体最终位置的逻辑(如相机跟随、视差背景),在所有Update执行完毕后调用,确保拿到最新的物体位置,避免画面不同步。

脚本修改方案

1. Player Movement Script 优化

将isGrounded物理碰撞检测移到FixedUpdate(物理周期内检测更准确),输入与动画控制留在Update:

//Jump
public float jumpForce;
private bool isGrounded;
private Rigidbody2D rb;
[SerializeField] private UnityEngine.Transform groundCheck;
[SerializeField] private LayerMask groundLayer;
[SerializeField] private SpriteRenderer sb;

//Movement
public float speed;
bool moveRightPressed = false;
bool moveLeftPressed = false;
bool jumpPressed = false;
private float horizontalMove = 0;

//Animation
private Animator anim;

private void Awake()
{
    rb = GetComponent<Rigidbody2D>();
    sb = GetComponent<SpriteRenderer>();
    anim = GetComponent<Animator>();
}

//Check for Buttons
public void PointerDownMoveRight() => moveRightPressed = true;
public void PointerUpMoveRight() => moveRightPressed = false;
public void PointerDownMoveLeft() => moveLeftPressed = true;
public void PointerUpMoveLeft() => moveLeftPressed = false;
public void PointerDownJump() => jumpPressed = true;
public void PointerUpJump() => jumpPressed = false;

private void Update()
{
    // 动画状态同步渲染帧率更新
    anim.SetBool("isJumping", !isGrounded);

    if (moveLeftPressed)
    {
        horizontalMove = -speed;
        anim.SetBool("isRunning", true);
        sb.flipX = true;
    }
    else if (moveRightPressed)
    {
        horizontalMove = speed;
        anim.SetBool("isRunning", true);
        sb.flipX = false;
    }
    else
    {
        horizontalMove = 0;
        anim.SetBool("isRunning", false);
        sb.flipX = false;
    }
}

private void FixedUpdate()
{
    // 物理周期内检测碰撞状态,保证准确性
    isGrounded = Physics2D.OverlapCircle(groundCheck.position, 0.2f, groundLayer);
    
    // 修改刚体物理属性
    rb.velocity = new Vector2(horizontalMove, rb.velocity.y);
    
    if (jumpPressed && isGrounded)
    {
        rb.velocity = Vector2.up * jumpForce;
        anim.SetTrigger("takeOf");
    }
}

2. Camera Movement Script 调整到LateUpdate

将相机跟随逻辑移到LateUpdate,确保拿到Player最新物理位置,同时优化平滑速度适配不同帧率:

public Transform target; //Player
public float smoothSpeed = 10f;  
public Vector3 offset;

private void LateUpdate()
{
    Vector3 desiredPosition = new Vector3(target.position.x + offset.x, transform.position.y, transform.position.z);
    // 用Time.deltaTime保证不同帧率下平滑效果一致
    Vector3 smoothedPosition = Vector3.Lerp(transform.position, desiredPosition, smoothSpeed * Time.deltaTime);
    transform.position = smoothedPosition;
}

3. Parallax Background Script 调整到LateUpdate

视差背景依赖相机位置,移到LateUpdate避免与物理周期不同步导致卡顿:

private float length, startpos;
public GameObject cam;
public float parallaxEffect;

private void Start()
{
    startpos = transform.position.x;
    length = GetComponent<SpriteRenderer>().bounds.size.x;
}

private void LateUpdate()
{
    float dist = cam.transform.position.x * parallaxEffect;
    transform.position = new Vector3(startpos + dist, transform.position.y, transform.position.z);
    
    // 可选:无限滚动逻辑,背景超出相机范围时重置位置
    if (transform.position.x < startpos - length)
    {
        startpos -= length;
    }
}

卡顿原因解析

  • 相机放在FixedUpdate时,更新频率与渲染帧率不同步:渲染帧率高于物理帧率时相机会跳帧,低于时会重复渲染同一帧,导致静态平台看起来卡顿。
  • isGrounded放在Update时,碰撞状态滞后于物理模拟,可能导致跳跃判断不准确,间接带来卡顿感。

内容的提问来源于stack exchange,提问作者DanxAG

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 15:45:32