如何在Unity中实现带升降变速的3D对象空闲浮动动画并优化实现
浮动动画优化方案
原代码的实际问题
- 手动堆了方向、进度、速度、加速度一堆状态变量,写得啰嗦就算了,逻辑还和需求反了:到最高点反向的时候,代码里存的速度是全流程最大值,然后下落过程中速度逐渐减小,也就是下落越来越慢,和你要的「下降逐渐加速、上升逐步放缓」的效果完全不沾边
- 每帧固定累加进度,没接
Time.deltaTime,高帧率设备上会飘得特别快 - 硬编码了Y轴的最小/最大值,把对象挪到别的位置后,动画会直接把物体拽到预设的固定Y值上
- 边界判断容易因为浮点精度问题出bug,比如进度刚好卡在0或者1的时候来回震荡
不需要复杂状态机的实现思路
你说的用Mathf.PingPong的方向是对的,根本不用自己维护方向反向的逻辑:
Mathf.PingPong本身就能输出0到1再回到0的往返值,自动帮你处理周期切换- 只要给这个往返值套一层不对称的缓动公式,就能刚好匹配你要的速度曲线:
eased = t * (2 - t)- 上升阶段(PingPong值从0升到1):用一半的上升时间就能走完75%的路程,越靠近最高点速度越慢,刚好是上升逐步放缓的效果
- 下落阶段(PingPong值从1降到0):用一半的下落时间才走25%的路程,越靠近最低点速度越快,刚好是下落逐渐加速的效果
简化后的代码
public class IdleAnimation : MonoBehaviour { [Header("浮动参数")] [Tooltip("垂直浮动的总幅度")] public float floatRange = 0.4f; [Tooltip("完成一次完整上下浮动的周期(秒)")] public float floatCycleTime = 2f; private Vector3 _originPos; private float _timer; void Start() { // 缓存物体初始位置,不需要硬编码坐标 _originPos = transform.position; } void Update() { _timer += Time.deltaTime; // 拿0-1范围的PingPong往返值 float pingValue = Mathf.PingPong(_timer / floatCycleTime, 1f); // 套缓动曲线,生成不对称的速度变化 float easedValue = pingValue * (2f - pingValue); // 把缓动值映射为Y轴偏移 float targetY = _originPos.y + (easedValue - 0.5f) * floatRange; // 只更新Y值,保留原来的X/Z位置 transform.position = new Vector3(_originPos.x, targetY, _originPos.z); } }
关于Mathf.SmoothStep的误区
很多人第一反应会套Mathf.SmoothStep,但它生成的是完全对称的S型曲线——上升和下降过程都是两头慢、中间快,根本没办法实现你要的“上升减速、下落加速”的不对称效果。如果想要更强的动态感,只要改缓动公式就行,比如换成三次曲线easedValue = Mathf.Pow(pingValue, 3f),就能得到更明显的慢上快下的效果。
内容的提问来源于stack exchange,提问作者Xyloking17
相关产品推荐
相关产品推荐

