【Unity】Animation、Animator 和 Spine 的动画状态重置

这里提到的重置主要解决一个问题,就是动画重复播放时,和第一次播放的表现不同,或者动画异常中断后,下一次播放效果不符合期待。

Animation

        /// <summary>
        /// 重置Animation动画状态
        /// </summary>
        public static void ResetAnimation(Animation ani, string name, bool toEnd = false)
        {
            AnimationState state = ani[name];
            ani.Play(name);
            if (toEnd)
                state.time = state.length; // 重置到动画结束
            else
                state.time = 0;            // 重置到动画一开始
            ani.Sample();                  // 及时更新到期待帧
            state.enabled = false;         // 暂停动画直至下次启用
        }

这里的 toEnd 参数是当时为了某个特殊需求另加的,可以将动画状态重置到最后一帧的状态,同理通过修改 state.time 可以将动画状态重置到任意时刻

Animator

首先 Animator 的一般播放方法本身就是会重置动画状态的:

    // 参数:动画名,层,时间
    animator.Play("animName", -1, 0f);

网上关于Animator的重置,有一段广为流传的代码是在这一行后加 animator.Update(0f); 经测试发现毫无意义,默认的动画推进间隔本来就是0,重新设置一下动画的播放表现不会有任何异样表现。倘若期望重置动画状态后暂停动画的播放,则应该调用 animator.speed = 0f;

不过直接调用播放函数来重置状态也有意外情况,重复播放异常可以考虑使用以下方法重置状态:
animator.Rebind(); // 考虑性能消耗时慎用

这里补充一个判断 Animator 片段播放结束的方法:

        private void Update()
        {
            if(m_bCheckEnd)
            {
                AnimatorStateInfo stateInfo = animator.GetCurrentAnimatorStateInfo(0);
                if(stateInfo.IsName("ClipName")                 /* 正在播放消失 */
                    && false == stateInfo.loop                  /* 不是循环片段 */
                    && stateInfo.normalizedTime >= 1)           /* 已经播放结束 */
                {
                    m_bCheckEnd = false;
                    
                    //TODO 结束后要执行的方法
                }
            }
        }

Spine

        var trackEntry = spine.AnimationState.SetAnimation(0, "ClipName", false); 
        trackEntry.TimeScale = 0f;   // 把动画暂停到第0帧
        trackEntry.MixDuration = 0f; // 取消动画变换的过渡效果

大部分情况使用上述方法将动画重置到下次播放的0帧状态就满足重复播放的需求了

还有一些有关 spine 的重置方法需要深入了解才能合理应用,这里先列一下:

// 这一系列函数会直接把Spine动画重置为空状态,
// 现实应用时可能有些属性我们不想重置,
// 这就需要有选择地删减方法。
spine.AnimationState.ClearTracks();
spine.Skeleton.SetToSetupPose();
spine.Skeleton.UpdateWorldTransform();
spine.AnimationState.SetEmptyAnimation(0, 0f);
spine.Update(0);
spine.LateUpdate();
Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐