【Unity3D / Animation】实时动画,使Animation不受TimeScale影响

Unity 中的 Animation 组件播放动画时,依赖 Time.deltaTime 进行采样计算播放进度,如果游戏中改变了 timeScale 的值,则使用 Animation 制作动画也会受到影响,例如游戏胜利时的慢动作特写镜头,如果是依赖 timeScale 实现的,那么此时 UI 上的动画效果也都会一起变慢。

Animation 组件与粒子系统类似,通过每一帧采样播放,查看源码可以看到如下接口:

    /// 
    ///   Samples animations at the current state.
    /// 
    public void Sample()
    {
      Animation.INTERNAL_CALL_Sample(this);
    }

因此只需要制作一个组件,在动画播放时,每一帧使用非缩放时间重新计算动画的播放进度,并采样播放,直接给出代码如下:

    [RequireComponent(typeof(Animation))]
    public class RealTimeAnimation : MonoBehaviour
    {
        public Animation Animation { get; set; }

        public void Awake()
        {
            Animation = GetComponent<Animation>();
            IsPlaying = false;
        }

        private float _lastFrameTime;
        private float _currentTime;
        private float _progressTime;

        public bool IsPlaying { get; set; }

        public void OnEnable()
        {
            if (Animation.playAutomatically)
            {
                Play();
            }
        }

        public void Play()
        {
            _progressTime = 0f;
            _lastFrameTime = Time.realtimeSinceStartup;
            IsPlaying = true;
        }

        public void Update()
        {
            if (!IsPlaying) return;
            var clip = Animation.clip;
            var state = Animation[clip.name];
            _currentTime = Time.realtimeSinceStartup;
            var deltaTime = _currentTime - _lastFrameTime;
            _lastFrameTime = _currentTime;
            _progressTime += deltaTime * state.speed;
            state.normalizedTime = _progressTime / clip.length;
            Animation.Sample();
            if (_progressTime >= clip.length)
            {
                IsPlaying = false;
            }
        }
    }

1.当动画勾选自动播放 PlayAutomatically时,则会自动调用Play()接口进行播放。
2.每一帧的时间为非缩放的两帧时间间隔,并且乘上动画片段本身设置的播放倍速。
3.默认实现仅自动播放一次,适用于UI打开等一次性自动触发的动画,其他播放模式自行按需修改。

你可能感兴趣的:(Unity3D,C#,.NET)