Unity中使用Cinemachine实现第三人称相机时出现移动及旋转卡顿问题
卡顿原因及修复方案
核心问题点
- 方向计算逻辑放在
Update中执行,但角色移动、旋转的物理逻辑都在FixedUpdate中执行,两者刷新频率不匹配:转动相机时direction会在Update中实时更新,但FixedUpdate的执行频率固定,会导致角色旋转、移动的更新延迟,出现卡顿感 - 原代码将速度值直接赋值给了
direction变量,后续逻辑复用容易出错 - Cinemachine虚拟相机的更新模式如果和物理帧绑定,也会和屏幕刷新频率不匹配,导致相机转动卡顿
代码修改方案
public class ThirdPersonScript : MonoBehaviour { [SerializeField] private float speed; [SerializeField] private float jumpForce; [SerializeField] private float rotateSpeed = 1080f; // 旋转参数单独抽离方便调整 [SerializeField] private Transform feet; [SerializeField] private LayerMask floorMask; [SerializeField] private Transform cam; private Vector3 inputDir; // 单独存储原始输入方向 private Vector3 moveDir; // 存储经相机校准后的移动方向 private Rigidbody rb; private bool canJump; void Start() { rb = GetComponent<Rigidbody>(); } // Update仅负责采集输入 void Update() { inputDir = new Vector3(Input.GetAxis("Horizontal"), 0f, Input.GetAxis("Vertical")); canJump = Input.GetKeyDown(KeyCode.Space); } // 所有物理、角色变换相关逻辑统一放在FixedUpdate执行,相机角度计算也同步挪到此处 void FixedUpdate() { // 基于当前相机角度计算实际移动方向 moveDir = Quaternion.AngleAxis(cam.rotation.eulerAngles.y, Vector3.up) * inputDir; if (moveDir.magnitude > 1f) { moveDir.Normalize(); } // 处理跳跃和移动逻辑 if (Physics.CheckSphere(feet.position, 0.1f, floorMask)) { if (canJump) rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse); else rb.velocity = new Vector3(moveDir.x * speed, 0, moveDir.z * speed); } else rb.velocity = new Vector3(moveDir.x * speed, rb.velocity.y, moveDir.z * speed); // 处理角色朝向逻辑 if (moveDir != Vector3.zero) { Quaternion targetRotation = Quaternion.LookRotation(moveDir); Quaternion newRotation = Quaternion.RotateTowards(transform.rotation, targetRotation, rotateSpeed * Time.fixedDeltaTime); rb.MoveRotation(newRotation); } // 重置跳跃标记,避免FixedUpdate多帧重复触发跳跃 canJump = false; } }
Cinemachine参数调整
打开Cinemachine虚拟相机的Inspector面板,找到Update Method选项,将值修改为LateUpdate,保证相机在每帧所有业务逻辑执行完成后再刷新位置/旋转,避免和物理帧冲突导致的卡顿。
内容的提问来源于stack exchange,提问作者Dusk
相关产品推荐
相关产品推荐

