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的累积误差也会导致角度偏移。
修正后的实现步骤
配置动画曲线
在Inspector中确保你的AnimationCurve满足:- X轴范围:0到1(对应旋转的归一化时间)
- Y轴范围:0到1(对应插值权重,0代表起始角度,1代表目标角度)
你的曲线是先加速后减速的形态,只要保证终点Y值为1即可。
修改协程代码
引入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
相关产品推荐
相关产品推荐

