您的位置:首页 > 编程语言 > Lua

Lua监听AniamtionEvent

2020-03-01 03:53 1016 查看
 

 

using System;
using System.Text;
using UnityEngine;
//using LuaInterface;
//using UnityEngine.Events;
using System.Collections.Generic;

namespace LuaFramework
{
    [RequireComponent(typeof(Animator))]
    public class AnimEventListener : MonoBehaviour
    {
        public readonly object EMPTY_ARG = new object();

        private Animator animator;

        private Dictionary<string, AnimEvent> eventsMap;

        private StringBuilder strBuilder;

        public delegate void ObjectDelegate(object arg0);

        public delegate void VoidDelegate();

        public static AnimEventListener Get(GameObject go)
        {
            if (go == null)
                return null;

            AnimEventListener listener = go.GetComponent<AnimEventListener>();

            if (listener == null)
                listener = go.AddComponent<AnimEventListener>();
            
            return listener;
        }

        void Awake()
        {
            animator = GetComponent<Animator>();
            strBuilder = new StringBuilder ();
            eventsMap = new Dictionary<string, AnimEvent>();
        }

        //该gameObject上的animator组件的所有animation事件统一回调到这
        public void OnAnimEvent(AnimationEvent animEvent)
        {
            if (animEvent == null) return;

            AnimEvent eventParam = null;
            if (eventsMap.TryGetValue(animEvent.stringParameter, out eventParam))
            {
                eventParam.Invoke();
            }

        }

        private bool _AddEvent(string animName, string animEventName, float time, AnimEvent eventParam)
        {
            //接下来通过animName找到对应的animation clip
            AnimationClip[] clips = animator.runtimeAnimatorController.animationClips;
            AnimationClip target = null;

            for (int i = 0; i < clips.Length; i++)
            {
                if (animName == clips[i].name)
                {
                    target = clips[i];
                    break;
                }
            }

            if (target == null) 
            {
                Debug.LogWarningFormat 
                ("not found animation clip #{0}# on GameObject #{1}#", animName, gameObject.name);
                return false;
            }
            //创建一个AnimationEvent:
            //此gameObject所有的animation事件统一回调到OnAnimEvent()函数上
            AnimationEvent animEvent = new AnimationEvent();
            animEvent.time = time;
            animEvent.functionName = "OnAnimEvent";
            animEvent.stringParameter = animEventName;
            eventsMap[animEventName] = eventParam;
            target.AddEvent(animEvent);
            return true;
        }

        /// <summary>
        /// 监听无参回调函数事件
        /// </summary>
        // Tolua Wrap带委托参数类型的函数不支持重载,暂时用后缀区分,可用LuaFunction代替
        public bool AddEvent1(string animName, float time, VoidDelegate callback)
        {
            string animEventName = GetAnimEventName (animName, time);

            //如果animEventName没被监听过
            AnimEvent eventParam = null;
            if (!eventsMap.TryGetValue(animEventName, out eventParam))
            {
                eventParam = new AnimEvent(callback);
                eventParam.animName = animName;
                eventParam.animEventname = animEventName;
                return _AddEvent (animName, animEventName, time, eventParam);
            }
            else
            {
                eventParam.AddListener(callback);
            }
            return true;
        }

        /// <summary>
        /// 监听有参回调函数事件
        /// <animName> 动画名称
        /// <time> 动画事件出发时刻(time <= animName总长度)
        /// <callback> 动画事件回调函数
        /// <arg0> 动画事件回调函数参数
        /// </summary>
        // Tolua Wrap带委托参数类型的函数不支持重载,暂时用后缀区分,可用LuaFunction代替
        public bool AddEvent2(string animName, float time, ObjectDelegate callback, object arg0)
        {

            string animEventName = GetAnimEventName (animName, time, arg0);

            if (string.IsNullOrEmpty (animEventName))
                return false;
            //如果animEventName没被监听过
            AnimEvent eventParam = null;
            if (!eventsMap.TryGetValue(animEventName, out eventParam))
            {
                eventParam = new AnimEvent(arg0, callback);
                eventParam.animName = animName;
                eventParam.animEventname = animEventName;
                return _AddEvent (animName, animEventName, time, eventParam);
            }
            else
            {
                eventParam.AddListener(callback);
            }
            return true;
        }
        //移除name为animaName的animation clip所有监听
        public void RemoveEvent(string animName)
        {
            List<string> events = new List<string> ();
            foreach (var item in eventsMap) 
            {
                if (item.Value.animName.Equals(animName)) 
                {
                    item.Value.RemoveAllListeners ();
                    events.Add (item.Key);
                }
            }

            foreach (var item in events) 
            {
                eventsMap.Remove (item);
            }
        }

        //移除name为animaName的animation clip在time时刻所有的监听
        public void RemoveEvent(string animName, float time)
        {
            string pattern = string.Format ("{0}_{1}", animName, time);
            List<string> events = new List<string> ();

            foreach (var item in eventsMap) 
            {
                AnimEvent ae = item.Value;
                if (item.Key.StartsWith(pattern) && !ae.animName.Equals(pattern)) 
                {
                    ae.RemoveAllListeners ();
                    events.Add (item.Key);
                }
            }

            foreach (var item in events) 
            {
                eventsMap.Remove (item);
            }

        }
            

        //获取animation event name
        private string GetAnimEventName(string animName, float time, object arg0 = null)
        {

            //StringBuild:效率高,线程非安全。多线程可以用StringBuffer
            //animation name,trigger time,arg0的HashCode拼接作为事件的唯一标识符
            strBuilder.Remove (0, strBuilder.Length);
            strBuilder.AppendFormat ("{0}_{1}", animName, time);
            strBuilder.Append ('_');

            if (arg0 == null) 
            {
                strBuilder.Append (EMPTY_ARG.GetHashCode ());
            } else 
            {
                strBuilder.Append (arg0.GetHashCode ());
            }

            return strBuilder.ToString ();
        }

        private void ClearEventsMap()
        {
            if (eventsMap == null)
                return;
            
            foreach (var item in eventsMap) 
            {
                item.Value.RemoveAllListeners ();
            }
        }

        void OnDestroy()
        {
            ClearEventsMap ();
        }

        public void Print(){
            foreach (var item in eventsMap) {
                Debug.LogFormat ("eventName:{0}", item.Key);
            }
        }

        public class AnimEvent
        {
            private object arg0;
            private event ObjectDelegate m_objectEvent;
            private event VoidDelegate m_voidEvent;
            public string animName;
            public string animEventname;
            public AnimEvent(object arg0, ObjectDelegate callback)
            {
                this.arg0 = arg0;
                m_objectEvent += callback;
                m_voidEvent = null;
            }


            public AnimEvent(VoidDelegate callback)
            {
                arg0 = null;
                m_objectEvent = null;
                m_voidEvent += callback;
            }

            public void Invoke()
            {
                if (m_objectEvent != null) 
                {
                    m_objectEvent (arg0);
                } 
                else if (m_voidEvent != null) 
                {
                    m_voidEvent ();
                }
            }

            public void AddListener(VoidDelegate callback)
            {
                m_voidEvent += callback;
            }

            public void RemoveListener(VoidDelegate callback)
            {
                m_voidEvent -= callback;
            }

            public void AddListener(ObjectDelegate callback)
            {
                m_objectEvent += callback;
            }

            public void RemoveListener(ObjectDelegate callback)
            {
                m_objectEvent -= callback;
            }

            public void RemoveAllListeners()
            {
                m_objectEvent = null;
                m_voidEvent = null;
            }

        }
    }
}
使用实例:
1 local UE = UnityEngine
2 local GO = UE.GameObject
3 local LF = LuaFramework
4 local AEL = LF.AnimEventListener
7
8 function Main()
9     player = GO.Find("Player")
10     --在player的"run"动画播放1s时添加一个事件
11     AEL.Get(player):AddEvent1("Run", 1, OnRunOneSecond)
12     animator = player:GetComponent(typeof(UE.Animator)) end
15
30 function OnRunOneSecond()
31     print("OnRunOneSecond")
32 end

 



转载于:https://www.cnblogs.com/xsxjin/p/6838906.html

  • 点赞
  • 收藏
  • 分享
  • 文章举报
anhui2031 发布了0 篇原创文章 · 获赞 0 · 访问量 62 私信 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: