Unity中使用LookAt实现相机跟随抖动,如何实现平滑跟随?
相机平滑跟随的解决方案
嘿,我来帮你搞定相机颤抖的问题~你当前的代码是直接硬赋值相机位置+用LookAt瞬间旋转,这种“跳变”操作很容易因为帧率波动、目标移动的帧同步问题导致颤抖——毕竟目标的移动逻辑在Update,相机也在Update,有时候目标还没完成当前帧的移动,相机就先更新了,自然会出现抽搐感。
下面给你两种平滑跟随的实现方案,都能解决这个问题:
方案1:线性插值(Lerp)实现基础平滑
这种方式简单直观,适合大多数场景:
修改你的cubeCamera脚本为下面的代码:
public class cubeCamera : MonoBehaviour { public Transform target; // 调整这个值控制移动平滑度,越大越快跟上目标 public float smoothMoveSpeed = 5f; // 调整这个值控制旋转平滑度,越大越快转向目标 public float smoothRotateSpeed = 10f; // 相机相对于目标的固定偏移量 private Vector3 cameraOffset; void Start() { // 初始化偏移:用相机初始位置减去目标初始位置,保持初始相对位置 cameraOffset = transform.position - target.position; } void LateUpdate() { if (target == null) return; // 计算相机需要到达的目标位置 Vector3 targetPosition = target.position + cameraOffset; // 平滑移动相机位置 transform.position = Vector3.Lerp(transform.position, targetPosition, smoothMoveSpeed * Time.deltaTime); // 计算相机需要朝向的目标旋转 Quaternion targetRotation = Quaternion.LookRotation(target.position - transform.position); // 平滑旋转相机 transform.rotation = Quaternion.Lerp(transform.rotation, targetRotation, smoothRotateSpeed * Time.deltaTime); } }
关键优化点:
- 改用
LateUpdate:确保相机在目标完成当前帧的移动后再更新,避免帧同步导致的位置偏差 - 用
Vector3.Lerp做位置平滑:每次帧只移动一小段距离到目标位置,不会突然跳变 - 用
Quaternion.Lerp做旋转平滑:旋转也是渐进式过渡,不会瞬间转头导致颤抖 - 初始化偏移量:灵活保留相机和目标的初始相对位置,不用硬编码数值
方案2:平滑阻尼(SmoothDamp)实现更自然的缓动效果
如果想要更柔和的“缓入缓出”跟随效果(比如目标突然加速时,相机慢慢跟上,不会生硬拉扯),可以用Vector3.SmoothDamp:
修改后的代码如下:
public class cubeCamera : MonoBehaviour { public Transform target; // 平滑时间,值越大跟随越柔和,越小越灵敏 public float smoothTime = 0.1f; // 旋转平滑速度 public float smoothRotateSpeed = 10f; private Vector3 cameraOffset; // 用于SmoothDamp的速度缓存变量 private Vector3 currentMoveVelocity; void Start() { cameraOffset = transform.position - target.position; } void LateUpdate() { if (target == null) return; Vector3 targetPosition = target.position + cameraOffset; // 用SmoothDamp实现带缓动的平滑移动 transform.position = Vector3.SmoothDamp(transform.position, targetPosition, ref currentMoveVelocity, smoothTime); Quaternion targetRotation = Quaternion.LookRotation(target.position - transform.position); transform.rotation = Quaternion.Lerp(transform.rotation, targetRotation, smoothRotateSpeed * Time.deltaTime); } }
小提示:
- 你可以根据实际游戏手感调整
smoothMoveSpeed、smoothRotateSpeed或者smoothTime的值,找到最舒服的跟随效果 - 如果目标的移动有物理引擎参与(比如Rigidbody),记得把相机的逻辑也放在
LateUpdate,避免物理更新和相机更新不同步导致的抖动
内容的提问来源于stack exchange,提问作者AxOn




