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
相关产品推荐
相关产品推荐

