Unity中Cinemachine相机随玩家速度平滑缩放问题求助
Cinemachine相机随玩家速度平滑缩放问题解决
问题背景
从Unreal引擎转Unity开发简易无尽跑酷游戏,期望通过玩家speed变量调整2D Cinemachine相机Body面板中的camera distance,实现玩家加速时相机缓慢拉远、碰撞减速时缓慢拉近,但所有尝试均导致相机瞬间跳变到目标值,无法实现平滑过渡。
错误原因分析
Mathf.Lerp参数误用:第三个参数应为0~1的插值比例,原代码中zoomSpeed = 10f远大于1,直接导致相机瞬间跳转到目标值。- 更新时机不合理:使用
InvokeRepeating以0.5秒间隔更新,无法保证平滑连贯的过渡效果。 - 重复获取组件:每次更新时重复调用
GetComponent,既浪费性能也可能引发意外问题。
修正后的相机脚本
public class CameraScript : MonoBehaviour { public GameObject player; private float currentCamDistance; private float targetCamDistance; private float camMax = 120f; private float camMin = 40f; [SerializeField] private float smoothZoomSpeed = 2f; // 建议取值1~5,控制平滑快慢 private CinemachineFramingTransposer framingTransposer; private MovementScript playerMovement; void Start() { // 提前缓存所需组件,避免重复调用 framingTransposer = GetComponent<CinemachineVirtualCamera>().GetCinemachineComponent<CinemachineFramingTransposer>(); playerMovement = player.GetComponent<MovementScript>(); currentCamDistance = framingTransposer.m_CameraDistance; } void Update() { UpdateCameraZoom(); } void UpdateCameraZoom() { // 根据玩家速度计算目标相机距离,可根据需求调整公式 targetCamDistance = playerMovement.speed + 20f; // 先限制目标值范围,避免超出边界 targetCamDistance = Mathf.Clamp(targetCamDistance, camMin, camMax); // 基于时间的平滑插值,保证不同帧率下效果一致 currentCamDistance = Mathf.Lerp(currentCamDistance, targetCamDistance, smoothZoomSpeed * Time.deltaTime); // 应用到相机组件 framingTransposer.m_CameraDistance = currentCamDistance; } }
玩家脚本补充(碰撞减速逻辑)
如果需要实现碰撞障碍物减速的效果,在MovementScript中添加以下代码:
private void OnControllerColliderHit(ControllerColliderHit hit) { // 检测碰撞到障碍物标签的物体时减速 if (hit.gameObject.CompareTag("Obstacle")) { speed = Mathf.Max(speed - 10f, 6f); // 最低速度不小于初始值6 multiplier = Mathf.Max(multiplier - 2f, 1f); // 乘数最低不小于1 } }
关键注意事项
- 正确使用
Mathf.Lerp:必须将平滑速度与Time.deltaTime相乘,确保跨帧率的平滑一致性。 - 组件缓存:在
Start中提前获取所需组件,避免每帧重复查询。 - 更新时机:将缩放逻辑放在
Update中每帧执行,替代InvokeRepeating以保证过渡流畅。 - 先限制范围再插值:先对目标相机距离做
Clamp限制,再进行插值计算,避免超出边界后的跳变。
内容的提问来源于stack exchange,提问作者GDBlue
相关产品推荐
相关产品推荐

