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

如何实现摄像机向上后坐效果?寻求非协程实现方案

摄像机向上后坐实现(无协程方案)

核心思路

替代协程的帧循环逻辑,改用Update驱动+时间变量控制插值进度,通过维护状态变量来管理后坐的「抬起-回落」阶段,既避免协程的上下文依赖,也能更精准控制动画节奏。


方案一:时间驱动的线性插值(带平滑过渡)

适合需要精准控制抬起/回落时长的场景,用Mathf.SmoothStep让动画更自然。

步骤1:定义成员变量

// 后坐状态控制
private bool _isCameraRecoilActive = false;
private float _recoilTimer = 0f;

// 后坐参数(可挂载到枪械配置中)
public float cameraRecoilUpForce = 0.5f; // 向上抬起的幅度
public float recoilUpDuration = 0.1f;    // 抬起动作时长
public float recoilDownDuration = 0.2f;  // 回落动作时长

// 摄像机初始位置缓存
private Vector3 _cameraOriginPos;

步骤2:触发后坐的调用方法

在射击逻辑中调用此方法启动后坐:

public void TriggerCameraRecoil()
{
    if (!_isCameraRecoilActive)
    {
        _cameraOriginPos = Camera.main.transform.localPosition;
        _isCameraRecoilActive = true;
        _recoilTimer = 0f;
    }
}

步骤3:Update帧更新处理

void Update()
{
    if (!_isCameraRecoilActive) return;

    _recoilTimer += Time.deltaTime;
    Vector3 targetPos;
    float progress;

    // 阶段1:摄像机向上抬起
    if (_recoilTimer <= recoilUpDuration)
    {
        progress = Mathf.SmoothStep(0f, 1f, _recoilTimer / recoilUpDuration);
        targetPos = new Vector3(_cameraOriginPos.x, _cameraOriginPos.y + cameraRecoilUpForce, _cameraOriginPos.z);
        Camera.main.transform.localPosition = Vector3.Lerp(_cameraOriginPos, targetPos, progress);
    }
    // 阶段2:摄像机回落至初始位置
    else if (_recoilTimer <= recoilUpDuration + recoilDownDuration)
    {
        progress = Mathf.SmoothStep(0f, 1f, (_recoilTimer - recoilUpDuration) / recoilDownDuration);
        targetPos = new Vector3(_cameraOriginPos.x, _cameraOriginPos.y + cameraRecoilUpForce, _cameraOriginPos.z);
        Camera.main.transform.localPosition = Vector3.Lerp(targetPos, _cameraOriginPos, progress);
    }
    // 阶段3:结束后坐,重置状态
    else
    {
        Camera.main.transform.localPosition = _cameraOriginPos;
        _isCameraRecoilActive = false;
    }
}

方案二:Vector3.SmoothDamp 平滑阻尼(更简洁的动态过渡)

Unity内置的平滑阻尼函数,自动处理加速度/减速度,适合追求自然手感的场景,无需手动拆分阶段。

步骤1:定义成员变量

private bool _isCameraRecoilActive = false;
private Vector3 _cameraOriginPos;
public float cameraRecoilUpForce = 0.5f;

// 平滑参数
private Vector3 _currentVelocity = Vector3.zero;
public float smoothTime = 0.1f; // 平滑时间,越小动画越快
public float recoilHoldTime = 0.05f; // 最高点停留时长
private float _holdTimer = 0f;

步骤2:触发方法同方案一

public void TriggerCameraRecoil()
{
    if (!_isCameraRecoilActive)
    {
        _cameraOriginPos = Camera.main.transform.localPosition;
        _isCameraRecoilActive = true;
        _holdTimer = 0f;
        _currentVelocity = Vector3.zero;
    }
}

步骤3:Update帧更新处理

void Update()
{
    if (!_isCameraRecoilActive) return;

    Vector3 targetPos = new Vector3(_cameraOriginPos.x, _cameraOriginPos.y + cameraRecoilUpForce, _cameraOriginPos.z);

    // 先移动到最高点并停留
    if (_holdTimer <= recoilHoldTime)
    {
        Camera.main.transform.localPosition = Vector3.SmoothDamp(
            Camera.main.transform.localPosition, 
            targetPos, 
            ref _currentVelocity, 
            smoothTime
        );

        // 接近最高点时开始计时停留
        if (Vector3.Distance(Camera.main.transform.localPosition, targetPos) < 0.01f)
        {
            _holdTimer += Time.deltaTime;
        }
    }
    // 回落至初始位置
    else
    {
        Camera.main.transform.localPosition = Vector3.SmoothDamp(
            Camera.main.transform.localPosition, 
            _cameraOriginPos, 
            ref _currentVelocity, 
            smoothTime * 2 // 回落慢一点,手感更真实
        );

        // 回到初始位置后结束后坐
        if (Vector3.Distance(Camera.main.transform.localPosition, _cameraOriginPos) < 0.01f)
        {
            Camera.main.transform.localPosition = _cameraOriginPos;
            _isCameraRecoilActive = false;
        }
    }
}

关键注意事项

  1. 初始位置缓存:必须在触发后坐时记录摄像机初始位置,避免多次触发导致位置偏移。
  2. 参数调优:根据枪械手感调整recoilUpForce(幅度)、recoilUpDuration(抬起速度)等参数,狙击枪可以调慢回落速度,冲锋枪调快。
  3. 多枪械适配:可以把后坐参数(如cameraRecoilUpForce)挂载到枪械脚本中,和你现有retroActionForce一样动态获取。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 14:12:06