unity-消息的注册,监听,回调
最近在空闲时间准备做个小游戏,先把一些基本框架搭建好,本次记录的是消息的注册,监听和回调等
其实这些就是基于C#的委托(delegate)
第一步:定义一些委托
namespace Common.Messenger
{
public delegate void Callback();
public delegate void Callback<T>(T arg1);
public delegate void Callback<T, U>(T arg1, U arg2);
public delegate void Callback<T, U, V>(T arg1, U arg2, V arg3);
public delegate void Callback<T, U, V, W>(T arg1, U arg2, V arg3, W arg4);
public delegate void Callback<T, U, V, W, X>(T arg1, U arg2, V arg3, W arg4, X arg5);
public delegate void Callback<T, U, V, W, X, Y>(T arg1, U arg2, V arg3, W arg4, X arg5, Y arg6);
public delegate T CallbackReturn<T>();
public delegate T CallbackReturn<T, U>(U arg1);
}
用泛型的方式灵活运用各种消息处理
第二步:定义两个Message类,用于add/remove/brocast消息
namespace Common.Messenger
{
public enum MessengerMode : byte
{
DONT_REQUIRE_LISTENER,
REQUIRE_LISTENER,
}
private static internal class MessengerInternal
{
//......
}
public static class Messenger
{
//....
}
}
MessengerInternal类:用于存放消息类型,结构Dictionary<string,Delegate>
static internal class MessengerInternal
{
public static Dictionary<string, Delegate> eventTable = new Dictionary<string, Delegate>();
public static readonly MessengerMode DEFAULT_MODE = MessengerMode.DONT_REQUIRE_LISTENER;
public static void OnListenerAdding(string eventType, Delegate listenerBeingAdded)
{
if (!eventTable.ContainsKey(eventType))
eventTable.Add(eventType, null);
Delegate d = eventTable[eventType];
if(d!=null&&d.GetType()!=listenerBeingAdded.GetType())
throw new ListenerException(string.Format("Attempting to add listener with inconsistent signature for event type {0}. Current listeners have type {1} and listener being added has type {2}", eventType, d.GetType().Name, listenerBeingAdded.GetType().Name));
}
public static void OnListenerMoving(string eventType,Delegate listenerBeingRemoved)
{
if (eventTable.ContainsKey(eventType))
{
Delegate d = eventTable[eventType];
if (d == null)
throw new ListenerException(string.Format("Attempting to remove listener with for event type {0} but current listener is null.", eventType));
else if(d.GetType()!=listenerBeingRemoved.GetType())
throw new ListenerException(string.Format("Attempting to remove listener with inconsistent signature for event type {0}. Current listeners have type {1} and listener being removed has type {2}", eventType, d.GetType().Name, listenerBeingRemoved.GetType().Name));
}
else
throw new ListenerException(string.Format("Attempting to remove listener for type {0} but Messenger doesn't know about this event type.", eventType));
}
public static void OnListenerRemoved(string eventType)
{
if (eventTable[eventType] == null)
eventTable.Remove(eventType);
}
public static void OnBroadcasting(string eventType, MessengerMode mode)
{
if(mode==MessengerMode.REQUIRE_LISTENER&&!eventTable.ContainsKey(eventType))
throw new MessengerInternal.BroadcastException(string.Format("Broadcasting message {0} but no listener found.", eventType));
}
static public BroadcastException CreateBroadcastSignatureException(string eventType)
{
return new BroadcastException(string.Format("Broadcasting message {0} but listeners have a different signature than the broadcaster.", eventType));
}
public class BroadcastException : Exception
{
public BroadcastException(string msg)
: base(msg)
{
}
}
public class ListenerException : Exception
{
public ListenerException(string msg):base(msg)
{
}
}
}
Messenger类:Public类型,用于外界的调用,封装了AddListener/Remove/Brocast的方法
public static class Messenger
{
private static Dictionary<string, Delegate> eventTable = MessengerInternal.eventTable;
public static void AddListener(string eventType,Callback handler)
{
MessengerInternal.OnListenerAdding(eventType, handler);
eventTable[eventType] = (Callback)eventTable[eventType] + handler;
}
public static void RemoveListener(string eventType, Callback handler)
{
MessengerInternal.OnListenerMoving(eventType, handler);
eventTable[eventType] = (Callback)eventTable[eventType] - handler;
MessengerInternal.OnListenerRemoved(eventType);
}
public static void Broadcast(string eventType)
{
Broadcast(eventType, MessengerInternal.DEFAULT_MODE);
}
public static void Broadcast(string eventType, MessengerMode mode)
{
MessengerInternal.OnBroadcasting(eventType, mode);
Delegate d;
if (eventTable.TryGetValue(eventType, out d))
{
Callback callback = d as Callback;
if (callback != null)
callback();
else
throw MessengerInternal.CreateBroadcastSignatureException(eventType);
}
}
}
Messenger<T>类:含参数的扩展类
public static class Messenger<T>
{
private static Dictionary<string, Delegate> eventTable = MessengerInternal.eventTable;
public static void AddListener(string eventType, Callback<T> handler)
{
MessengerInternal.OnListenerAdding(eventType, handler);
eventTable[eventType] = (Callback<T>)eventTable[eventType] + handler;
}
public static void RemoveListener(string eventType, Callback<T> handler)
{
MessengerInternal.OnListenerMoving(eventType, handler);
eventTable[eventType] = (Callback<T>)eventTable[eventType] - handler;
}
public static void Broadcast(string eventType, T arg1)
{
Broadcast(eventType, arg1, MessengerInternal.DEFAULT_MODE);
}
public static void Broadcast(string eventType, T arg1, MessengerMode mode)
{
MessengerInternal.OnBroadcasting(eventType, mode);
Delegate d;
if (eventTable.TryGetValue(eventType,out d))
{
Callback<T> callback = d as Callback<T>;
if (callback != null)
callback(arg1);
}
else
throw MessengerInternal.CreateBroadcastSignatureException(eventType);
}
}
Messenger<T, U>:同上
举例:下面是一个消息弹窗例子
UI层调用
void OnStartClick(GameObject go)
{
UIMessageMgr.ShowMessBox("?????", () => { Debug.Log("Success"); });
}
UIMessageMgr:
public static void ShowMessBox(string content, Callback ok)
{
Messenger<string, Callback>.Broadcast(MessengerEventDef.ShowMessBox, content, ok);
//MessengerEventDef.ShowMessBox 是一个string,也就是Dictionary<>中的key
}
注册:
public override void RegisterMessage()
{
Messenger<string, Callback>.AddListener(MessengerEventDef.ShowMessBox, ShowMessBox);
}
移除监听:
public override void RemoveMessage()
{
Messenger<string, Callback>.RemoveListener(MessengerEventDef.ShowMessBox, ShowMessBox);
}
以上功能就是通过消息来显示提示框,使用的Message<T,U>,普通的消息可以用Message<T>
Client和Server之间的协议通信也用消息,Message<协议类>
//Message<协议类>.AddListener("这是一个字符串",回调方法)
//回调方法
//function(协议类)
//{
// 执行内容
//}
//Remove同上
//分发消息在接收到server的消息时把消息brocast
//function(协议类)
//{
// Message<协议类>.Brocast("这是一个字符串",协议类)
//}

浙公网安备 33010602011771号