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
- 点赞
- 收藏
- 分享
- 文章举报
相关文章推荐
- Unity-动画系统-AniamtionEvent
- Android_ UEventObserver_监听USB插拔
- 给自定义View添加TouchEvent事件监听
- C#中的delegate和event,WF中传递参数和监听事件会用到
- JS事件监听 JS:attachEvent和addEventListener 使用方法
- 马士兵 J2SE 第11章 GUI编程 事件模型ACTIONEVENT TEXTFIELD事件监听 内部类 PAINT adapter和repaint window事件 键盘事件
- Activity实现上下左右滑动监听onTouchEvent()方法
- js监听事件方法addEventListener()兼容非IE和attachEvent()兼容IE
- 关于lua中事件监听,多次请求网络的问题
- (转载)JS事件监听 JS:attachEvent和addEventListener使用方法
- 事件监听addEventListener----attachEvent
- javascript attachEvent addEventListener 监听事件
- oracle 监听hang,监听日志报错:WARNING: Subscription for node down event still pending' in Listener Log
- JS添加/绑定事件监听函数并传参数attachEvent和addEventListener兼容个浏览器
- 24.Nginx监听套接字读事件处理函数ngx_event_accept
- acegi流程分析之一《Acegi 中的HttpSessionEvent 监听机制 窥视Acegi的 工作流程》
- UI EventSystem事件监听
- cocos2d JS touch屏幕点击事件监听 cc.EventListener.TOUCH
- Lua监听AnimationEvent
- 监听事件绑定(addEventListener、attachEvent)和移除(removeEventListener、detachEvent)