Unity脚本设置动画跳至最后关键帧、抖动异常如何解决
问题原因
你的代码存在3个核心逻辑错误,直接导致了异常表现:
- 动画创建、播放逻辑错误放入了每帧执行的
LateUpdate(或Update/FixedUpdate)中:每帧都会重新创建AnimationClip、重复向Animation组件添加同名动画片段、反复触发Play()重置动画播放进度,相当于动画永远在第0帧和刚启动的状态反复跳,重复添加的clip还会导致动画播放状态堆叠,出现速度越来越快、抖动跳变的问题。 - 旋转属性绑定方式错误:
localRotation是Quaternion类型,x/y/z/w四个分量不是独立的线性值,不能单独拆分做曲线插值;且你设置的动画起始关键帧四个分量全为0,根本不是合法的四元数值(单位四元数起始值w应为1),动画系统无法正确插值,就会直接跳转到结束帧。 - 动画起始值未取骨骼当前真实状态:你硬编码起始旋转为全0值,和骨骼挂载时的初始旋转不匹配,会导致动画起始帧就跳变。
修复方法
- 把所有动画初始化、创建、绑定逻辑全部移到
Start()生命周期中,保证全局只执行1次 - 不要直接操作
localRotation的四个分量,改用localEulerAngles做角度插值,逻辑更直观也不会出现四元数插值异常 - 动画播放逻辑只需要在初始化完成后调用一次,不要每帧重复触发
- 曲线起始值取骨骼当前的初始欧拉角,结束值为目标旋转角度,保证插值平滑
修复后的完整代码如下:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class DeformBone : MonoBehaviour { // 动画总时长5秒,和原逻辑保持一致 public float animDuration = 5f; // 目标Z轴旋转角度 public float targetZAngle = 5f; void Start() { // 初始化逻辑仅执行一次 SetupRotationAnimation(); } private void SetupRotationAnimation() { // 取当前骨骼初始欧拉角作为动画起始值,避免跳变 Vector3 startEuler = transform.localEulerAngles; Vector3 endEuler = new Vector3(startEuler.x, startEuler.y, startEuler.z + targetZAngle); // 创建欧拉角插值曲线 AnimationCurve rotXCurve = AnimationCurve.EaseInOut(0, startEuler.x, animDuration, endEuler.x); AnimationCurve rotYCurve = AnimationCurve.EaseInOut(0, startEuler.y, animDuration, endEuler.y); AnimationCurve rotZCurve = AnimationCurve.EaseInOut(0, startEuler.z, animDuration, endEuler.z); AnimationClip clip = new AnimationClip(); clip.legacy = true; // 绑定localEulerAngles曲线,不直接操作四元数分量 clip.SetCurve("", typeof(Transform), "localEulerAngles.x", rotXCurve); clip.SetCurve("", typeof(Transform), "localEulerAngles.y", rotYCurve); clip.SetCurve("", typeof(Transform), "localEulerAngles.z", rotZCurve); // 初始化Animation组件 Animation animation = GetComponent<Animation>(); if (animation == null) { animation = gameObject.AddComponent<Animation>(); } animation.playAutomatically = false; animation.wrapMode = WrapMode.PingPong; // 注册并播放动画,仅执行一次 animation.AddClip(clip, "rotateyo"); animation.Play("rotateyo"); } }
补充说明:如果后续需要动态修改旋转目标,不建议用legacy动画实现,直接在LateUpdate中手动对
transform.localRotation做插值即可,逻辑更灵活,也不容易和骨骼原有动画产生冲突。
内容的提问来源于stack exchange,提问作者moonwindsailing
相关产品推荐
相关产品推荐

