这里提供了两种 EventDispatcher 实现:一种使用哈希表(Hashtable)以字符串作为 key 存储事件监听器,适合灵活的事件命名;另一种使用数组配合 const int 事件类型索引,性能比哈希表更快,适合事件类型固定的场景。

完整代码

using UnityEngine;
                using System.Collections;
                using System;
                using System.Collections.Generic;
                
                
                // this is custom event (use string0
                public class EventDispatcher : ZT_Object
                {
                    private EventDispatcher()
                    {
                        EventSystem.ins.AddEvent_Update(this);
                    }
                    Hashtable objs = new Hashtable();
                    Hashtable objs_for_once = new Hashtable();
                
                
                    public static EventDispatcher ins
                    {
                        get
                        {
                            return EventDispatcher.GetInstance();
                        }
                    }
                
                    private static EventDispatcher _ins = null;
                
                    public static EventDispatcher GetInstance()
                    {
                        if (_ins == null)
                        {
                            _ins = new EventDispatcher();
                        }
                        return _ins;
                    }
                
                
                    public static void DestroyInstance()
                    {
                        _ins.Clear();
                        _ins = null;
                    }
                
                    public static EventDispatcher Create(string name = "UnName")
                    {
                        EventDispatcher ret = new EventDispatcher();
                        ret.name = name;
                
                        return ret;
                    }
                
                
                    public void PostEvent(string type, object userdata = null)
                    {
                        if (objs.ContainsKey(type))
                        {
                            ArrayList list = objs[type] as ArrayList;
                
                            for( int i=0;i<list.Count;i++ )
                            {
                                ZT_Object obj = list[i] as ZT_Object;
                
                                obj.OnEvent(type, userdata);
                            }
                        }
                    }
                
                
                    public void PostEventOnce(string type, object userdata = null)
                    {
                        //call for once
                        if (objs_for_once.ContainsKey(type))
                        {
                            ArrayList list = objs_for_once[type] as ArrayList;
                
                            foreach (ZT_Object obj in list)
                            {
                                obj.OnEvent(type, userdata);
                            }
                            objs_for_once.Remove(type);
                        }
                
                    }
                
                
                    public void AddEventListener(ZT_Object target, string type)
                    {
                        if (objs.ContainsKey(type) == false)
                        {
                            objs.Add(type, new ArrayList());
                        }
                        ArrayList list = objs[type] as ArrayList;
                
                        list.Add(target);
                    }
                
                
                    public void RemoveEventListener(ZT_Object target, string type)
                    {
                        if (objs.ContainsKey(type) == false)
                        {
                            return;
                        }
                        ArrayList list = objs[type] as ArrayList;
                
                        list.Remove(target);
                    }
                
                    public void Clear()
                    {
                        objs.Clear();
                    }
                
                
                    public void AddEventListenerOnce(ZT_Object target, string type)
                    {
                        if (objs_for_once.ContainsKey(type) == false)
                        {
                            objs_for_once.Add(type, new ArrayList());
                        }
                        ArrayList list = objs_for_once[type] as ArrayList;
                
                        list.Add(target);
                    }
                
                
                    public void AddFuncToMainThread(Func<int> func)
                    {
                        this._queue_funcs.Enqueue(func);
                    }
                
                    private void ProcessOtherThreadFunc()
                    {
                        _queue_funcs.Lock();
                
                        while (_queue_funcs.UnSafeEmpty() == false)
                        {
                            Func<int> func = _queue_funcs.UnSafeDequeue() as Func<int>;
                            func();
                        }
                
                        _queue_funcs.UnLock();
                    }
                
                    public override void Update()
                    {
                        this.ProcessOtherThreadFunc();
                    }
                    private ThreadSafeQueue _queue_funcs = new ThreadSafeQueue();
                
                    public string name = "Global";
                
                };
                
                
                //this is event which used int for Event
                
                public class ZTEventDispatcher : object
                {
                    private ZTEventDispatcher()
                    {
                        for (int i = 0; i < Event.MAX_EVENT_LENGTH; i++)
                        {
                            objs.Add(null);
                            objs_for_once.Add(null);
                        }
                
                    }
                    ArrayList objs = new ArrayList();
                    ArrayList objs_for_once = new ArrayList();
                
                
                    public static ZTEventDispatcher ins
                    {
                        get
                        {
                            return ZTEventDispatcher.GetInstance();
                        }
                    }
                
                    private static ZTEventDispatcher _ins = null;
                
                    public static ZTEventDispatcher GetInstance()
                    {
                        if (_ins == null)
                        {
                            _ins = new ZTEventDispatcher();
                        }
                        return _ins;
                    }
                
                
                    public static void DestroyInstance()
                    {
                        _ins.Clear();
                        _ins = null;
                    }
                
                    public static ZTEventDispatcher Create(string name = "UnName")
                    {
                        ZTEventDispatcher ret = new ZTEventDispatcher();
                        ret.name = name;
                
                        return ret;
                    }
                
                    public void PostEvent(int type, object userdata = null)
                    {
                
                        if (objs[type] == null)
                        {
                            return;
                        }
                        ArrayList list = objs[type] as ArrayList;
                
                        foreach (ZT_Object obj in list)
                        {
                            obj.OnEvent(type, userdata);
                        }
                
                    }
                
                    public void PostEventOnce(int type, object userdata = null)
                    {
                        //call for once
                        if (objs_for_once[type] != null)
                        {
                            ArrayList list = objs_for_once[type] as ArrayList;
                
                            foreach (ZT_Object obj in list)
                            {
                                obj.OnEvent(type, userdata);
                            }
                            objs_for_once.Remove(type);
                        }
                
                    }
                
                
                    public void AddEventListener(ZT_Object target, int type)
                    {
                        if (objs[type] == null)
                        {
                            objs[type] = new ArrayList();
                        }
                        ArrayList list = objs[type] as ArrayList;
                
                        list.Add(target);
                    }
                
                
                    public void RemoveEventListener(ZT_Object target, int type)
                    {
                        if (objs[type] == null)
                        {
                            return;
                        }
                        ArrayList list = objs[type] as ArrayList;
                
                        list.Remove(target);
                    }
                
                    public void Clear()
                    {
                        objs.Clear();
                    }
                
                
                    public void AddEventListenerOnce(ZT_Object target, int type)
                    {
                        if (objs_for_once[type] == null)
                        {
                            objs_for_once[type] = new ArrayList();
                        }
                        ArrayList list = objs_for_once[type] as ArrayList;
                
                        list.Add(target);
                    }
                
                
                
                
                    public string name = "GlobalZTEvent";
                
                };

ZT_Object

using UnityEngine;
                using System.Collections;
                using System;
                
                public class ZT_Object : IDisposable
                {
                
                
                    // every frame will be call
                    public virtual void Update()
                    {
                
                    }
                
                    //every logic frame will be call(Frame Sync to All clients)
                    public virtual void UpdateMS()
                    {
                
                    }
                
                    //use this to init you class
                    public virtual bool Init()
                    {
                        return true;
                    }
                
                    public virtual void OnEvent(string type, object userData)
                    {
                
                    }
                    public virtual void OnEvent(int type, object userData)
                    {
                
                    }
                
                    // you can override  this interface to release your Res ,Rem. must call base.OnExit when you override
                    public virtual void OnExit()
                    {
                
                    }
                
                
                    // you can use this interface to  notify class to release//OnExit will be call
                    // use this or Release()
                    public void Dispose()
                    {
                        this.OnExit();
                    }
                    // use this or Dispose()
                    public void Release()
                    {
                        this.Dispose();
                    }
                };

此外,ZT_Object 是客户端所有对象的父类,负责消息派发、事件响应、逻辑更新接口、每帧更新接口以及析构处理等功能。

EventDispatcher 运行在主线程,同时提供了从其他线程向主线程添加回调函数的机制。