理解:
在事件处理类Messenger中定义一个事件表,以键值对(事件,委托(事件的响应函数))的形式存放事件与委托;
并提供往事件表中添加事件监听,即添加键值对(事件,委托(事件的响应函数));从事件表中移除事件监听;广播事件(即调用事件的响应函数)。
对于一个普通类来说,通过向事件表中添加事件监听,可以方便其它类通过广播来调用该类的函数。
一、定义事件枚举
public enum GameEvent {
GameOver,
}
二、定义:添加事件监听,移除事件监听,广播事件
消息派发管理中心 Messenger
1.使用一个字典(Dictionary)来记录各种需要转发的信息, key为消息枚举, value为回调(c#委托)
2.向外界提供监听方法 void AddListener (注册回调)
3.向外界提供移除监听方法 void RemoveListener (移除回调)
4.向外界提供广播方法 void Broadcast (调用回调)
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;
internal static class Messenger {
public static Dictionary<GameEvent, Delegate> mEventTable = new Dictionary<GameEvent, Delegate>();
private static bool OnAddListener(GameEvent eventType, Delegate handler)
{
if(!mEventTable.ContainsKey(eventType))
{
mEventTable.Add(eventType, null);
}
Delegate d = mEventTable[eventType];
if(d != null && d.GetType() != handler.GetType())
{
Debug.LogError(eventType+ "加入监听回调与当前监听类型不符合,当前类型为" + d.GetType().Name + "加入类型为" + handler.GetType().Name);
return false;
}
return true;
}
private static bool OnRemoveListener(GameEvent eventType, Delegate handler)
{
if(mEventTable.ContainsKey(eventType))
{
Delegate d = mEventTable[eventType];
if(d == null)
{
Debug.LogError("试图移除" + eventType + ",但当前监听为空");
return false;
}
else if(d.GetType() != handler.GetType())
{
Debug.LogError("试图移除" + eventType + ",与当前类型不符合,当前类型" + d.GetType().Name);
return false;
}
}
else
{
Debug.LogError("Messenger不包含要移除的对象" + eventType);
return false;
}
return true;
}
//添加监听
public static void AddListener(GameEvent eventType, Callback handler)
{
if(!OnAddListener(eventType,handler))
{
return;
}
mEventTable[eventType] = (Callback)mEventTable[eventType] + handler;//一个事件可以添加多个委托
}
public static void AddListener<T>(GameEvent eventType, Callback<T> handler)
{
if(!OnAddListener(eventType,handler))
{
return;
}
mEventTable[eventType] = (Callback<T>)mEventTable[eventType] + handler;
}
//移除监听
public static void RemoveListener(GameEvent eventType, Callback handler)
{
if(!OnRemoveListener(eventType,handler))
{
return;
}
mEventTable[eventType] = (Callback)mEventTable[eventType] - handler;
if(mEventTable[eventType] == null)
{
mEventTable.Remove(eventType);
}
}
public static void RemoveListener<T>(GameEvent eventType, Callback<T> handler)
{
if (!OnRemoveListener(eventType, handler))
{
return;
}
mEventTable[eventType] = (Callback<T>)mEventTable[eventType] - handler;
if (mEventTable[eventType] == null)
{
mEventTable.Remove(eventType);
}
}
//广播监听
public static void Broadcast(GameEvent eventType)
{
if(!mEventTable.ContainsKey(eventType))
{
return;
}
Delegate d;
if(mEventTable.TryGetValue(eventType,out d))
{
Callback callback = d as Callback;
if(callback != null)
{
callback();
}
else
{
Debug.LogError("广播" + eventType + "为空");
}
}
}
public static void Broadcast<T>(GameEvent eventType, T arg1)
{
if (!mEventTable.ContainsKey(eventType))
{
return;
}
Delegate d;
if (mEventTable.TryGetValue(eventType, out d))
{
Callback<T> callback = d as Callback<T>;
if (callback != null)
{
callback(arg1);
}
else
{
Debug.LogError("广播" + eventType + "为空");
}
}
}
}
三、使用:添加事件监听,移除事件监听,广播事件
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class MainPanel : MonoBehaviour {
void OnEnable()
{
Messenger.AddListener(GameEvent.GameOver, OnGameOver);
}
void OnDisable()
{
Messenger.RemoveListener(GameEvent.GameOver, OnGameOver);
}
private void OnGameOver()
{
Debug.Log("GameOver");
}
...
public class Player : Entity {
void Update()
{
if(Input.GetMouseButtonDown(0))
{
Messenger.Broadcast(GameEvent.GameOver);
}
}
...
结果:当点击鼠标左键的时候,将会打印日志:GameOver
public delegate void Callback(); // 无参数委托
public delegate void Callback<T>(T arg1); // 含一个参数的委托