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

Unity下坡赛车游戏中基于速度的相机抖动功能失效问题排查

下坡赛车游戏相机抖动脚本无效问题排查与修复

问题描述

我正在开发一款下坡赛车游戏,想要通过不同程度的相机抖动来体现玩家车速的提升。目前的设置是:

  • 创建了名为CameraHolder的GameObject作为主相机(Main Camera)的父物体
  • CameraHolder上挂载了相机跟随脚本CameraFollow
  • 主相机上挂载了用于在Holder内实现抖动的CameraShake脚本

但现在抖动脚本完全没有作用,我怀疑自己对localPosition的用法有误解,或者逻辑本身存在问题,想请大家帮忙排查。

相机跟随脚本(CameraFollow)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CameraFollow : MonoBehaviour
{
    public Camera cam;
    public Transform player;
    public Vector3 offset;
    public float speed = 2f;
    public Rigidbody rb;
    public float startingFieldOfView = 60f;

    void FixedUpdate()
    {
        float interpolation = speed * Time.deltaTime;
        Vector3 cameraPosition = new Vector3(Mathf.Lerp(transform.position.x, player.position.x, interpolation), player.position.y + player.localScale.y + offset.y, player.position.z + -player.localScale.z + offset.z);
        // 根据刚体速度改变相机FOV
        transform.position = cameraPosition;
        cam.fieldOfView = Mathf.Lerp(cam.fieldOfView, startingFieldOfView + (rb.velocity.magnitude / 3), .1f);
    }
}

相机抖动脚本(CameraShake)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CameraShake : MonoBehaviour
{
    public Rigidbody player;
    public float shakeThreshold;
    public float shakeMagnitude;

    private void Update()
    {
        float x = Random.Range(-shakeMagnitude, shakeMagnitude);
        float y = Random.Range(-shakeMagnitude, shakeMagnitude);

        if (player.velocity.magnitude >= shakeThreshold)
        {
            transform.localPosition = new Vector3(x, y, transform.position.z);
        }
    }
}

问题分析与修复

你的脚本无效确实和localPosition的用法以及逻辑设计都有关系,我来逐一拆解并给出解决方案:

1. localPosition的核心误用

你当前代码里的这行是关键问题:

transform.localPosition = new Vector3(x, y, transform.position.z);

localPosition是相机相对于父物体CameraHolder的本地空间坐标,而transform.position.z是相机在世界空间的z坐标。把世界空间的z值赋值给本地空间的z轴,会导致相机的位置彻底偏离父物体的预期范围,看起来自然就像没有抖动效果。

正确的做法是保留相机初始的本地z坐标,只修改x和y轴的偏移:

transform.localPosition = new Vector3(x, y, transform.localPosition.z);

2. 抖动逻辑的两处缺陷

  • 无归位逻辑:当车速低于shakeThreshold时,你的脚本没有把相机移回父物体的中心位置,相机就会停留在最后一次抖动的偏移位置,体验很差。
  • 固定抖动幅度:需求是根据车速提升增强抖动,但你用了固定的shakeMagnitude,完全没有关联车速,达不到预期的速度反馈效果。

修复后的完整CameraShake脚本

我重新写了脚本,修复了上述问题,还添加了平滑过渡让抖动更自然:

using UnityEngine;

public class CameraShake : MonoBehaviour
{
    public Rigidbody player;
    public float shakeThreshold = 10f; // 触发抖动的最低车速
    public float baseShakeMagnitude = 0.1f; // 低速时的基础抖动幅度
    public float maxShakeMagnitude = 0.5f; // 高速时的最大抖动幅度
    public float smoothFactor = 5f; // 抖动平滑过渡的系数,值越大过渡越快

    private Vector3 originalLocalPos; // 保存相机初始的本地位置,用于抖动后归位

    private void Start()
    {
        // 游戏开始时记录相机的初始本地位置
        originalLocalPos = transform.localPosition;
    }

    private void Update()
    {
        float currentSpeed = player.velocity.magnitude;
        // 默认目标位置是初始的本地位置(无抖动状态)
        Vector3 targetPos = originalLocalPos;

        if (currentSpeed >= shakeThreshold)
        {
            // 根据当前车速计算抖动幅度,用Lerp在基础和最大值之间过渡
            float currentMagnitude = Mathf.Lerp(baseShakeMagnitude, maxShakeMagnitude, currentSpeed / 30f);
            // 生成随机的x、y轴偏移
            float xOffset = Random.Range(-currentMagnitude, currentMagnitude);
            float yOffset = Random.Range(-currentMagnitude, currentMagnitude);
            // 计算带偏移的目标位置
            targetPos = new Vector3(originalLocalPos.x + xOffset, originalLocalPos.y + yOffset, originalLocalPos.z);
        }

        // 使用Lerp实现平滑的位置过渡,避免抖动过于突兀
        transform.localPosition = Vector3.Lerp(transform.localPosition, targetPos, smoothFactor * Time.deltaTime);
    }
}

额外优化建议

  • 在CameraFollow脚本中,相机FOV的更新可以从FixedUpdate移到Update里,因为FOV是渲染相关的,和帧率同步会更流畅。
  • 可以尝试给抖动添加频率变化:比如车速越快,随机偏移的更新频率越高,进一步强化速度带来的紧张感(可以用Time.time % 0.1f < Time.deltaTime这样的逻辑控制每0.1秒生成一次新的偏移值)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 04:44:08