这里提供了两种 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 运行在主线程,同时提供了从其他线程向主线程添加回调函数的机制。