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

Unity协程转盘动画:集成动画曲线实现平滑变速遇阻

Unity转盘动画:用AnimationCurve实现平滑减速并精准停在目标角度

我在Unity项目中用协程实现了转盘旋转动画,原本的线性插值可以让转盘旋转指定时长后停在目标角度,但尝试集成AnimationCurve控制旋转速度时出现问题:转盘没有平滑减速到目标角度,反而直接停在了起始角度。

原代码片段:

public void RotateWheel() {
    StartCoroutine(SpinWheelCoroutine());
}
private IEnumerator SpinWheelCoroutine() {
    _wheel.transform.eulerAngles = new Vector3(0, 0, 0);
    float currentSecond = 0;
    int index = Random.Range(0, 8);
    float targetAngle = (360 * 5) + index * 45;
    float startAngle = 0;
    while (currentSecond < Second) {
        currentSecond += Time.deltaTime;
        float t = currentSecond / Second;
        float currentAngle = Mathf.Lerp(startAngle, targetAngle, t);
        _wheel.transform.eulerAngles = new Vector3(0, 0, currentAngle);
        yield return null;
    }
    Debug.Log($"index-{index}, targetAngle-{targetAngle},currentAngle-{_wheel.transform.eulerAngles.z}");
}

使用的动画曲线:
转盘旋转速度曲线


问题原因

之前的错误核心是动画曲线的取值逻辑错误:如果直接用曲线输出值作为Lerp的插值参数,但曲线的Y轴终点不是1,最终会导致插值权重回到0,转盘就会跳回起始角度。另外,协程循环中Time.deltaTime的累积误差也会导致角度偏移。

修正后的实现步骤

  1. 配置动画曲线
    在Inspector中确保你的AnimationCurve满足:

    • X轴范围:0到1(对应旋转的归一化时间)
    • Y轴范围:0到1(对应插值权重,0代表起始角度,1代表目标角度)
      你的曲线是先加速后减速的形态,只要保证终点Y值为1即可。
  2. 修改协程代码
    引入AnimationCurve变量,用曲线输出值替代线性的t值,并在循环结束后强制修正角度:

public AnimationCurve spinCurve; // 在Inspector中拖入配置好的动画曲线
public float spinDuration = 3f; // 转盘旋转总时长
private Transform _wheel;

public void RotateWheel() {
    StartCoroutine(SpinWheelCoroutine());
}

private IEnumerator SpinWheelCoroutine() {
    _wheel.transform.eulerAngles = Vector3.zero;
    float elapsedTime = 0f;
    int targetIndex = Random.Range(0, 8);
    // 总旋转角度:5圈 + 目标索引对应的角度
    float totalRotation = 360f * 5 + targetIndex * 45f;
    float startAngle = 0f;

    while (elapsedTime < spinDuration) {
        elapsedTime += Time.deltaTime;
        // 计算归一化时间,用Clamp01防止超出曲线范围
        float normalizedTime = Mathf.Clamp01(elapsedTime / spinDuration);
        // 从动画曲线获取当前插值权重
        float curveWeight = spinCurve.Evaluate(normalizedTime);
        // 根据曲线权重计算当前角度
        float currentAngle = Mathf.Lerp(startAngle, totalRotation, curveWeight);
        _wheel.transform.eulerAngles = new Vector3(0, 0, currentAngle);
        yield return null;
    }

    // 强制设置到目标角度,消除deltaTime累积的误差
    _wheel.transform.eulerAngles = new Vector3(0, 0, totalRotation);
    Debug.Log($"选中索引-{targetIndex}, 目标角度-{totalRotation}, 最终角度-{_wheel.transform.eulerAngles.z}");
}

关键说明

  • Mathf.Clamp01确保归一化时间不会超过1,避免动画曲线越界取值
  • 动画曲线Y轴必须从0过渡到1,保证最终插值权重为1,转盘精准到达目标角度
  • 循环结束后直接设置目标角度,解决协程中Time.deltaTime累积导致的角度误差

内容的提问来源于stack exchange,提问作者mr.Umang

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 03:14:55