为Unity3D的Animator动画片段增加播放完毕回调

利用AnimatorStateInfo信息来处理当前的动画信息。

目前没出现什么bug,回调也相对精准。

using System.Collections.Generic;
using UnityEngine;

namespace KT.Core
{ 
    /// <summary>
    /// Animator 播放动画回调相关
    /// </summary>
    public class AnimatorPlayCall : MonoBehaviour
    {
        List<AnimatorPlayCallParam> Pools = new List<AnimatorPlayCallParam>();

        static AnimatorPlayCall instance;
        public static AnimatorPlayCall I
        {
            get
            {
                if (instance == null)
                {
                    instance = new GameObject("AnimatorPlayCall").AddComponent<AnimatorPlayCall>();
                    GameObject.DontDestroyOnLoad(instance);
                }
                return instance;
            }
        }

        /// <summary>
        /// 检测Animator是否播放完毕
        /// </summary>
        /// <param name="animator"></param>
        /// <param name="name"></param>
        /// <param name="action"></param>
        public void OnIsPlayOver(Animator animator,bool isCurrent, System.Action action)
        {
            Pools.Add(new AnimatorPlayCallParam(animator, isCurrent, action));
        }

        void Update()
        {
            if (Pools.Count > 0)
            {
                for (int i = 0; i < Pools.Count; i++)
                {
                    if (Pools[i].Check())
                    {
                        Pools.Remove(Pools[i]);
                    }
                }
            }
        }

        /// <summary>
        /// 播放回调参数
        /// </summary>
        class AnimatorPlayCallParam
        {
            public AnimatorPlayCallParam(Animator animator, bool isCurrent, System.Action call)
            {
                Layer = 0;
                Action = call;
                Animator = animator;
                IsCurrent = isCurrent;
            }

            public AnimatorPlayCallParam(Animator animator, bool isCurrent,int layer, System.Action call)
            {
                Layer = layer;
                Action = call;
                Animator = animator;
                IsCurrent = isCurrent;
            }

            /// <summary>
            /// 层
            /// </summary>
            public int Layer { private set; get; }

            /// <summary>
            /// 回调行为
            /// </summary>
            public System.Action Action { private set; get; }

            /// <summary>
            /// Animator 动画
            /// </summary>
            public Animator Animator { private set; get; }

            /// <summary>
            /// 是否当前动画
            /// </summary>
            public bool IsCurrent { private set; get; }

            /// <summary>
            /// 缓存的NameHash
            /// </summary>
            private int shortNameHash=0;

            private AnimatorStateInfo CurInfo
            {
                get
                {
                    return Animator.GetCurrentAnimatorStateInfo(Layer);
                }
            }

            private AnimatorStateInfo NextInfo
            {
                get
                {
                    return Animator.GetNextAnimatorStateInfo(Layer);
                }
            }

            /// <summary>
            /// 每帧检测动画状态
            /// </summary>
            /// <returns></returns>
            public bool Check()
            {
                if(IsCurrent)
                {                    
                    if(shortNameHash == 0 && CurInfo.shortNameHash != 0)
                    {
                        shortNameHash = CurInfo.shortNameHash;
                    }
                }
                else
                {
                    if (shortNameHash == 0 && NextInfo.shortNameHash != 0)
                    {
                        shortNameHash = NextInfo.shortNameHash;
                    }
                }
                if (CurInfo.shortNameHash != shortNameHash && shortNameHash != NextInfo.shortNameHash)
                {
                    Action?.Invoke();
                    return true;
                }
                return false;
            }
        }
    }

    /// <summary>
    /// Animator扩展
    /// </summary>
    public static class AnimatorExtension
    {
        public static void SetTrigger(this Animator animater, string name, System.Action action)
        {
            animater.SetTrigger(name);
            AnimatorPlayCall.I.OnIsPlayOver(animater,false, action);
        }

        public static void SetBool(this Animator animater, string name, bool value, System.Action action)
        {
            animater.SetBool(name, value);
            AnimatorPlayCall.I.OnIsPlayOver(animater, false, action);
        }

        public static void Play(this Animator animater, string name, System.Action action)
        {
            animater.Play(name);
            AnimatorPlayCall.I.OnIsPlayOver(animater, true, action);
        }

        public static void OnOver(this Animator animater,bool isCurrent, System.Action action)
        {
            AnimatorPlayCall.I.OnIsPlayOver(animater, isCurrent, action);
        }
    }

}

猜你喜欢

转载自blog.csdn.net/l100142548/article/details/90142663