一、首先定义一份消息号(消息号用来标记发出的每一条消息,接收者通过注册要监听的消息号来监听相应的消息)
public enum MSG_IDS
{
NONE = -1,
MSG_TEST01 = 100000,
MSG_TEST02 = 100001,
}
二、然后定义一个消息类,作为消息的载体
public class Notification {
MSG_IDS id = MSG_IDS.NONE; //消息号
public MSG_IDS Id{get { return id; }}
Dictionary<string, object> infos;// 消息内容,消息要传递的具体信息
public Notification(MSG_IDS id)
{
this.id = id;
infos = new Dictionary<string, object>();
}
//消息索引器,用字符串做key(注意key不能重复)
public object this[string id]
{
get {
if(infos.ContainsKey(id))
{
return infos[id];
}else
{
Debug.LogError("不存在参数:" + id);
return null;
}
}
set {
if(infos.ContainsKey(id))
{
infos[id] = value;
}else
{
infos.Add(id, value);
}
}
}
}
三、组件ID生成器,这个主要用于标记组件内的事件,以便移除
public class IDCreator{
uint curMaxId = 0;
List<uint> recycleIndex = new List<uint>();
public uint GetNewID()
{
if (recycleIndex.Count > 0)
{
uint id = recycleIndex[recycleIndex.Count - 1];
recycleIndex.RemoveAt(recycleIndex.Count - 1);
return id;
}
if (curMaxId == UInt32.MaxValue)
{
Debug.LogError("ID 溢出");
return curMaxId;
}
return curMaxId++;
}
public void Recycle(uint id)
{
recycleIndex.Add(id);
}
}
四、消息管理器
public class MsgController{
public delegate void MsgDel(Notification notify);
private Dictionary<MSG_IDS, List<MsgDel>> MsgDic;
private Dictionary<uint, Dictionary<MSG_IDS, MsgDel>> MsgDicMap;
private static MsgController _instance = null;
public static MsgController Instance
{
get
{
if(_instance == null)_instance = new MsgController();
return _instance;
}
}
private static IDCreator _componentID = null;
/// <summary>
/// 组件唯一id生成器
/// </summary>
public static IDCreator ComponentID
{
get
{
if (_componentID == null) _componentID = new IDCreator();
return _componentID;
}
}
/// <summary>
/// 添加监听
/// </summary>
/// <param name="msgId"></param>
/// <param name="msg"></param>
public void AddNotification(uint index, MSG_IDS msgId, MsgDel msg)
{
try
{
if (MsgDic == null)
{
MsgDic = new Dictionary<MSG_IDS, List<MsgDel>>();
}
if (MsgDicMap == null)
{
MsgDicMap = new Dictionary<uint, Dictionary<MSG_IDS, MsgDel>>();
}
//按消息号保存消息列表
if (!MsgDic.ContainsKey(msgId))
{
List<MsgDel> list = new List<MsgDel>();
MsgDic.Add(msgId, list);
}
MsgDic[msgId].Add(msg);
//按id索引保存消息列表
if (!MsgDicMap.ContainsKey(index))
{
Dictionary<MSG_IDS, MsgDel> map = new Dictionary<MSG_IDS, MsgDel>();
MsgDicMap.Add(index, map);
}
MsgDicMap[index].Add(msgId, msg);
}catch(Exception e)
{ throw (e); }
}
/// <summary>
/// 移除一个组件上的所有事件
/// </summary>
/// <param name="index"></param>
public void RemoveAllNotification(uint index)
{
if(MsgDicMap.ContainsKey(index))
{
foreach (var map in MsgDicMap[index])
{
RemoveNotification(map.Key, map.Value);
}
MsgDicMap.Remove(index);
_componentID.Recycle(index);//回收id以便重复利用
}
}
/// <summary>
/// 移除某个id对应的监听事件
/// </summary>
/// <param name="msgId"></param>
/// <param name="msg"></param>
public void RemoveNotification(MSG_IDS msgId, MsgDel msg)
{
try
{
MsgDic[msgId].Remove(msg);
}catch(Exception e)
{
Debug.LogError("找不到消息:" + msgId);
throw(e);
}
}
/// <summary>
/// 发送通知
/// </summary>
/// <param name="notify"></param>
public void SendMsg(Notification notify)
{
try
{
if (MsgDic.ContainsKey(notify.Id))
{
List<MsgDel> msgs = MsgDic[notify.Id];
for (int i = 0; i < msgs.Count; i++)
{
msgs[i](notify);
}
}
}catch(Exception e)
{ throw (e); }
}
四、发送、接收消息实例
public class Sender : MonoBehaviour {
int n = 0;public void Btn1()
{
Notification notify = new Notification(MSG_IDS.MSG_TEST01);
notify["text"] = "第" + (++n) + "次 string ";
MsgController.Instance.SendMsg(notify);
}
int m = 0;public void Btn2()
{
Notification notify = new Notification(MSG_IDS.MSG_TEST02);
notify["value"] = ++m;
MsgController.Instance.SendMsg(notify);
}
}
public class Listener01 : MonoBehaviour
{
uint eventIndex = 0;
void OnEnable()
{
eventIndex = MsgController.ComponentID.GetNewID();//获取一个组件id,这个id的意义在于,当一个组件上加了很多监听时,不需要一个个移除。一个个移除很麻烦,也很容易出错
MsgController.Instance.AddNotification(eventIndex, MSG_IDS.MSG_TEST01, MsgListener01);
MsgController.Instance.AddNotification(eventIndex, MSG_IDS.MSG_TEST02, MsgListener02);
}
void OnDisable()
{
MsgController.Instance.RemoveAllNotification(eventIndex);//移除所有组件id为eventIndex的监听(并不关心eventIndex的值是多少)
}
public void MsgListener01(Notification notify)
{
string text = (string)notify["text"];
Debug.LogError(transform.name + " " + text);
}
public void MsgListener02(Notification notify)
{
int v = (int)notify["value"];
Debug.LogError(transform.name + " " + v.ToString());
}
}