unity中事件分发系统 EventDispatcher
2015-03-22 14:40
309 查看
出处:http://blog.csdn.net/u010019717
author:孙广东 时间:2015.3.21 23:00
不使用C#中的event关键字: 只是使用delegate和hashtable 进行事件的分发。
基本库如下:
使用的例子:新建两个游戏对象然后挂上脚本!
author:孙广东 时间:2015.3.21 23:00
不使用C#中的event关键字: 只是使用delegate和hashtable 进行事件的分发。
基本库如下:
namespace EventDispatcher { /// <summary> /// IEvent接口 /// </summary> public interface IEvent { /// <summary> /// Gets or sets the type. /// </summary> /// <value> /// type类型. /// </value> string type { get; set;} /// <summary> /// Gets or sets the target. /// </summary> /// <value> /// target目标. /// </value> object target { get; set; } } }
namespace EventDispatcher { /// <summary> /// 事件事件接口 /// </summary> public class Event : IEvent { // GETTER / SETTER /// <summary> /// The _type_string. /// </summary> private string _type_string; string IEvent.type { get { return _type_string; } set { _type_string = value; } } /// <summary> /// The _target_object. /// </summary> private object _target_object; object IEvent.target { get { return _target_object; } set { _target_object = value; } } ///<summary> /// Constructor ///</summary> public Event (string aType_str ) { // _type_string = aType_str; } /// <summary> /// Deconstructor /// </summary> //~Event ( ) //{ // Debug.Log ("Event.deconstructor()"); //} } }
namespace EventDispatcher { /// <summary> /// IEventDispatcher 事件分发接口,添加移除分发 /// </summary> public interface IEventDispatcher { /// <summary> /// 添加事件监听 /// </summary> /// <returns><c>true</c>, 如果事件成功被监听, <c>false</c> 失败 </returns> /// <param name="aEventType_string">A event type_string.</param> /// <param name="aEventDelegate">一个事件委托</param> bool addEventListener(string aEventType_string, EventDelegate aEventDelegate); /// <summary> /// 添加事件监听 /// </summary> /// <returns><c>true</c>, 如果事件成功被监听, <c>false</c> 失败 </returns> /// <param name="aEventType_string">A event type_string.</param> /// <param name="aEventDelegate">一个事件委托</param> /// <param name="eventDispatcherAddMode">Event dispatcher add mode.</param> bool addEventListener(string aEventType_string, EventDelegate aEventDelegate, EventDispatcherAddMode eventDispatcherAddMode); /// <summary> /// 是否有这个事件监听 /// </summary> /// <returns><c>true</c>, 这个监听已经有了, <c>false</c> 没有.</returns> /// <param name="aEventType_string">A event type_string.</param> /// <param name="aEventDelegate">一个事件委托</param> bool hasEventListener(string aEventType_string, EventDelegate aEventDelegate); /// <summary> /// 移除事件监听 /// </summary> /// <returns><c>true</c>, 被成功移除 <c>false</c> 失败</returns> /// <param name="aEventType_string">A event type_string.</param> /// <param name="aEventDelegate">一个事件委托</param> bool removeEventListener(string aEventType_string, EventDelegate aEventDelegate); /// <summary> /// 移除所有事件监听 /// </summary> /// <returns><c>true</c>, 成功, <c>false</c> 失败 </returns> bool removeAllEventListeners(); /// <summary> /// 分发广播事件 /// </summary> /// <returns><c>true</c>, 成功, <c>false</c> 失败</returns> /// <param name="aIEvent">A I event.</param> bool dispatchEvent(IEvent aIEvent); } }
// C# unity事件管理器 在哈希表中使用字符串,对委托和事件管理 // 不知道他们何时何地declared/defined 也允许使用事件。 using UnityEngine; using System.Collections; namespace EventDispatcher { /// <summary> /// Event delegateN事件委托 /// </summary> public delegate void EventDelegate ( IEvent iEvent ); /// <summary> /// Event listening mode. /// </summary> public enum EventDispatcherAddMode { DEFAULT, SINGLE_SHOT } public class EventDispatcher : IEventDispatcher { /// <summary> /// The mom_serialized object. /// </summary> private Hashtable _eventListenerDatas_hashtable = new Hashtable(); /// <summary> /// The _target_object. /// </summary> private object _target_object; ///<summary> /// Constructor ///</summary> public EventDispatcher (object aTarget_object ) { // _target_object = aTarget_object; } /// <summary> /// Deconstructor /// </summary> //~EventDispatcher ( ) //{ // Debug.Log ("EventDispatcher.deconstructor()"); //} /// <summary> /// Adds the event listener. /// </summary> /// <returns> /// The event listener. /// </returns> /// <param name='aEventName_string'> /// If set to <c>true</c> a event name_string. /// </param> /// <param name='aEventDelegate'> /// If set to <c>true</c> a event delegate. /// </param> public bool addEventListener(string aEventName_string, EventDelegate aEventDelegate) { return addEventListener (aEventName_string, aEventDelegate, EventDispatcherAddMode.DEFAULT); } /// <summary> /// Adds the event listener. /// </summary> /// <returns> /// The event listener. /// </returns> /// <param name='aEventName_string'> /// If set to <c>true</c> a event type_string. /// </param> /// <param name='aEventDelegate'> /// If set to <c>true</c> a event delegate. /// </param> /// <param name='aEventDispatcherAddMode'> /// If set to <c>true</c> event listening mode. /// </param> public bool addEventListener(string aEventName_string, EventDelegate aEventDelegate, EventDispatcherAddMode aEventDispatcherAddMode) { // bool wasSuccessful_boolean = false; // object aIEventListener = _getArgumentsCallee(aEventDelegate); // if (aIEventListener != null && aEventName_string != null) { // OUTER string keyForOuterHashTable_string = _getKeyForOuterHashTable (aEventName_string); if (!_eventListenerDatas_hashtable.ContainsKey(keyForOuterHashTable_string) ) { _eventListenerDatas_hashtable.Add(keyForOuterHashTable_string, new Hashtable()); } // INNER Hashtable inner_hashtable = _eventListenerDatas_hashtable[keyForOuterHashTable_string] as Hashtable; EventListenerData eventListenerData = new EventListenerData (aIEventListener, aEventName_string, aEventDelegate, aEventDispatcherAddMode); // string keyForInnerHashTable_string = _getKeyForInnerHashTable (eventListenerData); if (inner_hashtable.Contains(keyForInnerHashTable_string)) { //THIS SHOULD *NEVER* HAPPEN - REMOVE AFTER TESTED WELL Debug.Log("TODO (FIX THIS): Event Manager: Listener: " + keyForInnerHashTable_string + " is already in list for event: " + keyForOuterHashTable_string); } else { // ADD inner_hashtable.Add(keyForInnerHashTable_string, eventListenerData); wasSuccessful_boolean = true; //Debug.Log (" ADDED AT: " + keyForInnerHashTable_string + " = " + eventListenerData); } } return wasSuccessful_boolean; } /// <summary> /// Hases the event listener. /// </summary> /// <returns> /// The event listener. /// </returns> /// <param name='aIEventListener'> /// If set to <c>true</c> a I event listener. /// </param> /// <param name='aEventName_string'> /// If set to <c>true</c> a event name_string. /// </param> /// <param name='aEventDelegate'> /// If set to <c>true</c> a event delegate. /// </param> public bool hasEventListener(string aEventName_string, EventDelegate aEventDelegate) { // bool hasEventListener_boolean = false; // object aIEventListener = _getArgumentsCallee(aEventDelegate); // OUTER string keyForOuterHashTable_string = _getKeyForOuterHashTable (aEventName_string); if (_eventListenerDatas_hashtable.ContainsKey(keyForOuterHashTable_string)) { // INNER Hashtable inner_hashtable = _eventListenerDatas_hashtable[keyForOuterHashTable_string] as Hashtable; string keyForInnerHashTable_string = _getKeyForInnerHashTable (new EventListenerData (aIEventListener, aEventName_string, aEventDelegate, EventDispatcherAddMode.DEFAULT)); // if (inner_hashtable.Contains(keyForInnerHashTable_string)) { hasEventListener_boolean = true; } } return hasEventListener_boolean; } /// <summary> /// Removes the event listener. /// </summary> /// <returns> /// The event listener. /// </returns> /// <param name='aIEventListener'> /// If set to <c>true</c> a I event listener. /// </param> /// <param name='aEventName_string'> /// If set to <c>true</c> a event name_string. /// </param> /// <param name='aEventDelegate'> /// If set to <c>true</c> a event delegate. /// </param> public bool removeEventListener(string aEventName_string, EventDelegate aEventDelegate) { // bool wasSuccessful_boolean = false; // if (hasEventListener (aEventName_string, aEventDelegate)) { // OUTER string keyForOuterHashTable_string = _getKeyForOuterHashTable (aEventName_string); Hashtable inner_hashtable = _eventListenerDatas_hashtable[keyForOuterHashTable_string] as Hashtable; // object aIEventListener = _getArgumentsCallee(aEventDelegate); // INNER string keyForInnerHashTable_string = _getKeyForInnerHashTable (new EventListenerData (aIEventListener, aEventName_string, aEventDelegate, EventDispatcherAddMode.DEFAULT)); inner_hashtable.Remove(keyForInnerHashTable_string); wasSuccessful_boolean = true; } return wasSuccessful_boolean; } /// <summary> /// Removes all event listeners. /// </summary> /// <returns> /// The all event listeners. /// </returns> public bool removeAllEventListeners() { // bool wasSuccessful_boolean = false; //TODO, IS IT A MEMORY LEAK TO JUST RE-CREATE THE TABLE? ARE THE INNER HASHTABLES LEAKING? _eventListenerDatas_hashtable = new Hashtable(); return wasSuccessful_boolean; } /// <summary> /// Dispatchs the event. /// </summary> /// <returns> /// The event. /// </returns> /// <param name='aIEvent'> /// If set to <c>true</c> a I event. /// </param> public bool dispatchEvent(IEvent aIEvent) { // bool wasSuccessful_boolean = false; // _doAddTargetValueToIEvent (aIEvent); // OUTER string keyForOuterHashTable_string = _getKeyForOuterHashTable (aIEvent.type); int dispatchedCount_int = 0; if (_eventListenerDatas_hashtable.ContainsKey(keyForOuterHashTable_string)) { // INNER Hashtable inner_hashtable = _eventListenerDatas_hashtable[keyForOuterHashTable_string] as Hashtable; IEnumerator innerHashTable_ienumerator = inner_hashtable.GetEnumerator(); DictionaryEntry dictionaryEntry; EventListenerData eventListenerData; ArrayList toBeRemoved_arraylist = new ArrayList (); // while (innerHashTable_ienumerator.MoveNext()) { dictionaryEntry = (DictionaryEntry)innerHashTable_ienumerator.Current; eventListenerData = dictionaryEntry.Value as EventListenerData; //***DO THE DISPATCH*** //Debug.Log ("DISPATCH : "); //Debug.Log (" n : " + eventListenerData.eventName ); //Debug.Log (" from : " + aIEvent.target ); //Debug.Log (" to : " + eventListenerData.eventListener ); //Debug.Log (" del : " + eventListenerData.eventDelegate + " " + (eventListenerData.eventDelegate as System.Delegate).Method.DeclaringType.Name + " " + (eventListenerData.eventDelegate as System.Delegate).Method.Name.ToString()); eventListenerData.eventDelegate (aIEvent); //TODO - THIS IS PROBABLY FUNCTIONAL BUT NOT OPTIMIZED, MY APPROACH TO HOW/WHY SINGLE SHOTS ARE REMOVED //REMOVE IF ONESHOT if (eventListenerData.eventListeningMode == EventDispatcherAddMode.SINGLE_SHOT) { toBeRemoved_arraylist.Add (eventListenerData); } //MARK SUCCESS, BUT ALSO CONTINUE LOOPING TOO wasSuccessful_boolean = true; dispatchedCount_int++; } //CLEANUP ANY ONE-SHOT, SINGLE-USE EventListenerData toBeRemoved_eventlistenerdata; for (int count_int = toBeRemoved_arraylist.Count -1; count_int >= 0; count_int --) { toBeRemoved_eventlistenerdata = toBeRemoved_arraylist[count_int] as EventListenerData; removeEventListener (toBeRemoved_eventlistenerdata.eventName, toBeRemoved_eventlistenerdata.eventDelegate); } } return wasSuccessful_boolean; } /// <summary> /// _dos the add target value to I event. /// </summary> /// <param name='aIEvent'> /// A I event. /// </param> /// <exception cref='System.NotImplementedException'> /// Is thrown when a requested operation is not implemented for a given type. /// </exception> public void _doAddTargetValueToIEvent (IEvent aIEvent) { aIEvent.target = _target_object; } public void OnApplicationQuit() { //TODO, DO THIS CLEANUP HERE, OR OBLIGATE API-USER TO DO IT?? _eventListenerDatas_hashtable.Clear(); } private string _getKeyForOuterHashTable (string aEventName_string) { //SIMPLY USING THE EVENT NAME - METHOD USED HERE, IN CASE I WANT TO TWEAK THIS MORE... return aEventName_string; } private string _getKeyForInnerHashTable (EventListenerData aEventListenerData) { //VERY UNIQUE - NICE! return aEventListenerData.eventListener.GetType().FullName + "_" + aEventListenerData.eventListener.GetType().GUID + "_" + aEventListenerData.eventName + "_" + (aEventListenerData.eventDelegate as System.Delegate).Method.Name.ToString(); } public object _getArgumentsCallee (EventDelegate aEventDelegate) { return (aEventDelegate as System.Delegate).Target; } } }
namespace EventDispatcher { /// <summary> /// EventListenerData /// </summary> public class EventListenerData { /// <summary> /// The _event listener. /// </summary> private object _eventListener; public object eventListener { get { return _eventListener; } set { _eventListener = value; } } /// <summary> /// 事件名 /// </summary> private string _eventName_string; public string eventName { get { return _eventName_string; } set { _eventName_string = value; } } /// <summary> /// 事件委托 /// </summary> private EventDelegate _eventDelegate; public EventDelegate eventDelegate { get { return _eventDelegate; } set { _eventDelegate = value; } } private EventDispatcherAddMode _eventListeningMode; public EventDispatcherAddMode eventListeningMode { get { return _eventListeningMode; } set { _eventListeningMode = value; } } ///<summary> /// Constructor ///</summary> public EventListenerData (object aEventListener, string aEventName_string, EventDelegate aEventDelegate, EventDispatcherAddMode aEventListeningMode ) { _eventListener = aEventListener; _eventName_string = aEventName_string; _eventDelegate = aEventDelegate; _eventListeningMode = aEventListeningMode; } /// <summary> /// Deconstructor /// </summary> //~EventListenerData ( ) //{ //Debug.Log ("EventListenerData.deconstructor()"); //} } }
使用的例子:新建两个游戏对象然后挂上脚本!
namespace EventDispatcher { /// <summary> /// Test event. /// </summary> public class SampleEvent : Event { // GETTER / SETTER /// <summary> /// An example of event-specific data you can add in. /// </summary> private string _customValue_string; public string customValue { get { return _customValue_string; } set { _customValue_string = value; } } /// <summary> /// The Event Type Name /// </summary> public static string SAMPLE_EVENT = "SAMPLE_EVENT"; /// <summary> /// Initializes a new instance of the <see cref="com.rmc.projects.event_dispatcher.SampleEvent"/> class. /// </summary> /// <param name="aType_str">A type_str.</param> public SampleEvent (string aType_str ) : base (aType_str) { } /// <summary> /// Releases unmanaged resources and performs other cleanup operations before the /// <see cref="com.rmc.projects.event_dispatcher.SampleEvent"/> is reclaimed by garbage collection. /// </summary> //~SampleEvent ( ) //{ // Debug.Log ("SampleEvent.deconstructor()"); //} } }
using UnityEngine; namespace EventDispatcher { public class SampleObservedComponent : MonoBehaviour { /// <summary> /// The event dispatcher. /// </summary> public EventDispatcher eventDispatcher; /// <summary> /// Initializes a new instance of the <see cref="com.rmc.projects.event_dispatcher.SampleObservedComponent"/> class. /// </summary> public SampleObservedComponent () { eventDispatcher = new EventDispatcher (this); } ///<summary> /// Use this for initialization ///</summary> public void Start () { SampleEvent sampleEvent = new SampleEvent (SampleEvent.SAMPLE_EVENT); sampleEvent.customValue = "foo"; Debug.Log ("Dispatching: SampleEvent " + sampleEvent); eventDispatcher.dispatchEvent (sampleEvent); } /// <summary> /// Raises the destroy event. /// </summary> public void OnDestroy () { // CLEANUP MEMORY eventDispatcher.removeAllEventListeners(); eventDispatcher = null; } } }
using UnityEngine; namespace EventDispatcher { public class SampleObserverComponent : MonoBehaviour { /// <summary> /// The sample observed game object. /// </summary> public SampleObservedComponent sampleObservedGameObject; public void Start () { /* * 注意: 这里observer和observed是 MonoBehavior 子类 **/ sampleObservedGameObject.eventDispatcher.addEventListener (SampleEvent.SAMPLE_EVENT, _onSampleEvent); } void Update () { //Debug.Log (sampleObservedGameObject.eventDispatcher); } /// <summary> /// Raises the destroy event. /// </summary> public void OnDestroy () { // CLEANUP MEMORY sampleObservedGameObject.eventDispatcher.removeEventListener (SampleEvent.SAMPLE_EVENT, _onSampleEvent); } //-------------------------------------- // Events //-------------------------------------- /// <summary> /// _ons the sample event. /// </summary> /// <param name="aIEvent">A I event.</param> public void _onSampleEvent (IEvent aIEvent) { Debug.Log ("\tListening: _onSampleEvent() aIEvent: " + aIEvent + " with customValue: " + (aIEvent as SampleEvent).customValue); } } }
相关文章推荐
- Unity 3D 消息事件系统 NotificationCenter、CEventDispatcher事件分发机制
- [寒江孤叶丶的Cocos2d-x之旅_23]Cocos2d-x LUA实现事件分发器 lua EventDispatcher
- cocos EventDispatcher事件分发机制
- 【Unity】简单的事件分发系统
- unity中事件分发系统 EventDispatcher
- CCScriptEventDispatcher(quick扩展类 。用于lua 下的CCNode 事件分发)
- MTK SystemUI/系统深度定制修改与编辑------细数那些你所不知道的事件分发处理机制 dispatchTouchEvent
- unity中事件分发系统 EventDispatcher
- UnityEvent与C#事件系统性能对比
- Touch Event事件分发流程
- Android事件分发02——Activity的dispatchTouchEvent验证一把
- Android View框架总结(九)KeyEvent事件分发机制
- Input事件输入系统之应用MotionEvent触摸事件处理流程
- μCOS-II系统之事件(event)的使用规则及MUTEX实例
- Android 4.0 事件输入(Event Input)系统
- Android事件分发详解(三)——ViewGroup的dispatchTouchEvent()源码学习
- 【Unity3D API的学习与使用】Unity中的事件响应——UnityEvent
- Unity-动画系统-AniamtionEvent
- The Event System(Qt的事件系统 )
- Unity5.0 EventSystem事件系统的详细说明