Unity消息机制
在游戏设计中一定要考虑降低模块与模块之间,代码与代码之间的耦合度
using UnityEngine;
using System.Collections.Generic;
public delegate void CallBackDelegate(params object[] paramList);
public class MessageCenter
{
/// <summary>
/// 消息名与MessageHandler的映射
/// </summary>
private Dictionary<string, List<MessageHandler>> msgHandlersDic;
private static MessageCenter _msgInstance;
/// <summary>
/// 获取单例
/// </summary>
public static MessageCenter msgInstance
{
get
{
if (_msgInstance == null)
{
_msgInstance = new MessageCenter();
Debug.Log("创建了一个messageCenter");
}
return _msgInstance;
}
}
public MessageCenter()
{
msgHandlersDic = new Dictionary<string, List<MessageHandler>>();
}
/// <summary>
/// 注册一个游戏对象成为观察者
/// </summary>
/// <param name="observer">this 观察者</param>
/// <param name="msgName">消息名</param>
/// <param name="callback">响应此消息的事件,用于接收消息</param>
/// <param name="priority">响应此消息的事件的优先级</param>
public void RegObserver(Component observer, string msgName, CallBackDelegate callback, int priority)
{
RegObserver(msgName, new MessageHandler(observer, callback, priority));
}
/// <summary>
/// 注册一个游戏对象成为观察者
/// </summary>
/// <param name="msgName">消息名</param>
/// <param name="handler">观察者和观察者响应的事件</param>
public void RegObserver(string msgName, MessageHandler handler)
{
if (msgName == null || handler.callback == null)
return;
if (!msgHandlersDic.ContainsKey(msgName))
{
msgHandlersDic[msgName] = new List<MessageHandler>();
msgHandlersDic[msgName].Add(handler);
return;
}
//判断是否已经注册过相同的观察者和响应事件
foreach (MessageHandler item in msgHandlersDic[msgName])
{
if (handler == item) return;
}
//添加一个新的观察者进入观察者队列,并根据优先级排序
for (int i = 0; i < msgHandlersDic[msgName].Count; i++)
{
if (msgHandlersDic[msgName][i].priority > handler.priority)
{
msgHandlersDic[msgName].Insert(i, handler);
return;
}
}
msgHandlersDic[msgName].Add(handler);
}
/// <summary>
/// 移除观察者
/// </summary>
/// <param name="observer">this,移除自身观察者身份</param>
/// <param name="msgName">消息名</param>
/// <param name="callback">响应此消息的事件,用于接收消息</param>
/// <param name="priority">响应此消息的事件的优先级</param>
/// <returns></returns>
public bool RemoveObserver(Component observer, string msgName, CallBackDelegate callback)
{
if (msgName == null || callback == null) return false;
if (!msgHandlersDic.ContainsKey(msgName)) return false;
foreach(MessageHandler item in msgHandlersDic[msgName])
{
if (item.observer == observer && item.callback == callback)
return msgHandlersDic[msgName].Remove(item);
}
return false;
}
/// <summary>
/// 移除观察者
/// </summary>
/// <param name="msgName">消息名</param>
/// <param name="handler">观察者和观察者响应的事件</param>
/// <returns></returns>
public bool RemoveObserver(string msgName, MessageHandler handler)
{
if (msgName == null || handler.callback == null)
return false;
if (!msgHandlersDic.ContainsKey(msgName))
return false;
bool result = msgHandlersDic[msgName].Remove(handler);
if (msgHandlersDic[msgName].Count == 0)
msgHandlersDic.Remove(msgName);
return result;
}
/// <summary>
/// 发送消息
/// </summary>
/// <param name="msgName">消息名</param>
/// <param name="paramArray">发送的消息参数</param>
public void SendMessage(string msgName, params object[] paramArray)
{
if (!msgHandlersDic.ContainsKey(msgName) || msgName == null) return;
List<MessageHandler> handlersToRemove = new List<MessageHandler>();
foreach (MessageHandler item in msgHandlersDic[msgName])
{
{
if (item.observer.gameObject.activeInHierarchy == false)
{
handlersToRemove.Add(item);//如果当前观察者对象已经被destroy或者disable,移除此观察者
}
else
item.callback(paramArray);//否则,执行接受消息后的响应事件
}
}
foreach (MessageHandler item in handlersToRemove)
msgHandlersDic[msgName].Remove(item);
}
~MessageCenter()
{
msgHandlersDic = null;
Debug.Log("执行析构了");
}
}
/// <summary>
/// 观察者与响应事件封装类
/// </summary>
public class MessageHandler
{
private Component _observer;//任何游戏对象都可以成为观察者
private CallBackDelegate _callback;//接收消息后,响应的事件
private int _priority;//响应事件优先级
public Component observer { get { return _observer; } }
public CallBackDelegate callback { get { return _callback; } }
public int priority { get { return _priority; } }
public MessageHandler(Component observer, CallBackDelegate callback,int priority)
{
_observer = observer;
_callback = callback;
_priority = priority;
}
}
测试
using UnityEngine;
using System.Collections;
public class ObserverOne : MonoBehaviour
{
void OnEnable()
{
//注册自身成为观察者
MessageCenter.msgInstance.RegObserver(this, "testMsg", ReceiveMsg, 1);
}
public void ReceiveMsg(params object[] msg)
{
Debug.Log(this.name +" 接受到了: "+ msg[0]);
}
}
using UnityEngine;
using System.Collections;
public class ObserverTwo : MonoBehaviour
{
void OnEnable()
{
//注册自身成为观察者
MessageCenter.msgInstance.RegObserver(this, "testMsg", ReceiveMsg, 2);
}
public void ReceiveMsg(params object[] msg)
{
Debug.Log(this.name + " 接受到了: " + msg[0]);
}
}
using UnityEngine;
using System.Collections;
public class Test : MonoBehaviour {
/// <summary>
/// 按钮点击方法
/// </summary>
public void ClickAndSendMsg()
{
MessageCenter.msgInstance.SendMessage("testMsg", "这是一条消息");
}
}
将ClickAndSendMsg方法绑定到测试按钮上,测试结果