在开发中我们避免不了各个模块之间的消息传递,因此总结此消息收发机制。
MonoBase类
首先是扩展MonoBehaviour的基类:MonoBase
此类的就是为了让MonoBehaviour的功能更加强大
public class MonoBase : MonoBehaviour
{
/// <summary>
/// 定义一个虚方法
/// </summary>
public virtual void Execute(int eventCode, object message)
{
}
}
消息处理中心类:MessageCenter
只是负责消息的转发
public class MsgCenter : MonoBase
{
public static MsgCenter Instance = null;
void Awake()
{
Instance = this;
gameObject.AddComponent<AudioManager>();
gameObject.AddComponent<UIManager>();
gameObject.AddComponent<NetManager>();
gameObject.AddComponent<CharacterManager>();
gameObject.AddComponent<SceneMgr>();
DontDestroyOnLoad(gameObject);
}
/// <summary>
/// 发送消息 系统里面所有的发消息 都通过这个方法来发
/// 根据不同的模块 来转发给 不同的模块
/// 通过 areaCode识别模块
///
/// 第二个参数:事件码 作用?用来区分 做什么事情的
/// 比如说 第一个参数 识别到是角色模块 但是角色模块有很多功能 比如 移动 攻击 死亡 逃跑...
/// 就需要第二个参数 来识别 具体是做哪一个动作
/// </summary>
public void Dispatch(int areaCode, int eventCode, object message)
{
switch (areaCode)
{
case AreaCode.AUDIO:
AudioManager.Instance.Execute(eventCode, message);
break;
case AreaCode.CHARACTER:
CharacterManager.Instance.Execute(eventCode, message);
break;
case AreaCode.NET:
NetManager.Instance.Execute(eventCode, message);
break;
case AreaCode.GAME:
break;
case AreaCode.UI:
UIManager.Instance.Execute(eventCode, message);
break;
case AreaCode.SCENE:
SceneMgr.Instance.Execute(eventCode, message);
break;
default:
break;
}
}
}
游戏的模块类:
/// <summary>
/// 区域码 代表 模块
/// </summary>
public class AreaCode
{
/// <summary>
/// UI模块
/// </summary>
public const int UI = 0;
/// <summary>
/// GAME模块
/// </summary>
public const int GAME = 1;
/// <summary>
/// CHARACTER模块
/// </summary>
public const int CHARACTER = 2;
/// <summary>
/// NET模块
/// </summary>
public const int NET = 3;
/// <summary>
/// AUDIO模块
/// </summary>
public const int AUDIO = 4;
/// <summary>
/// SCENE模块
/// </summary>
public const int SCENE = 5;
//....
}
注册消息的类
/// <summary>
/// 每个模块的基类
/// 1。保存自身注册的一系列消息
/// </summary>
public class ManagerBase : MonoBase
{
/// <summary>
/// 处理自身的消息
/// </summary>
/// <param name="eventCode">Event code.</param>
/// <param name="message">Message.</param>
public override void Execute(int eventCode, object message)
{
if (!dict.ContainsKey(eventCode))
{
Debug.LogWarning("没有注册 : " + eventCode);
return;
}
//一旦注册过这个消息 给所有的脚本 发过去
List<MonoBase> list = dict[eventCode];
for (int i = 0; i < list.Count; i++)
{
list[i].Execute(eventCode, message);
}
}
/// <summary>
/// 存储 消息的事件码 和 哪个脚本 关联 的字典
///
/// 角色模块 有一个动作是 移动
/// 移动模块需要关心这个事件 控制角色位置 进行移动
/// 动画模块 也需要关心 控制角色播放动画
/// 音效模块 也需要关心 控制角色移动的音效播放 走路声
/// </summary>
private Dictionary<int,List<MonoBase>> dict = new Dictionary<int, List<MonoBase>>();
/// <summary>
/// 添加事件
/// </summary>
/// <param name="eventCode">Event code.</param>
/// <param name="mono">Mono.</param>
public void Add(int eventCode, MonoBase mono)
{
List<MonoBase> list = null;
//之前没有注册过
if (!dict.ContainsKey(eventCode))
{
list = new List<MonoBase>();
list.Add(mono);
dict.Add(eventCode, list);
return;
}
//之前注册过
list = dict[eventCode];
list.Add(mono);
}
/// <summary>
/// 添加多个事件
/// 一个脚本关心多个事件
/// </summary>
/// <param name="eventCode">Event code.</param>
public void Add(int[] eventCodes, MonoBase mono)
{
for (int i = 0; i < eventCodes.Length; i++)
{
Add(eventCodes[i], mono);
}
}
/// <summary>
/// 移除事件
/// </summary>
/// <param name="eventCode">Event code.</param>
/// <param name="mono">Mono.</param>
public void Remove(int eventCode, MonoBase mono)
{
//没注册过 没法移除 报个警告
if (!dict.ContainsKey(eventCode))
{
Debug.LogWarning("没有这个事件" + eventCode + "注册");
return;
}
List<MonoBase> list = dict[eventCode];
if (list.Count == 1)
dict.Remove(eventCode);
else
list.Remove(mono);
}
/// <summary>
/// 移除多个
/// </summary>
/// <param name="eventCode">Event code.</param>
/// <param name="mono">Mono.</param>
public void Remove(int[] eventCodes, MonoBase mono)
{
for (int i = 0; i < eventCodes.Length; i++)
{
Remove(eventCodes[i], mono);
}
}
}
以上就完成了一个简单的消息收发机制的框架
下面来简单介绍一下用法,例如我们在开发UI模块儿的时候
需要一个UIBase 作为该模块的基类
public class UIBase : MonoBase
{
/// <summary>
/// 自身关心的消息集合
/// </summary>
private List<int> list = new List<int>();
/// <summary>
/// 绑定一个或多个消息
/// </summary>
/// <param name="eventCodes">Event codes.</param>
protected void Bind(params int[] eventCodes)
{
list.AddRange(eventCodes);
UIManager.Instance.Add(list.ToArray(), this);
}
/// <summary>
/// 接触绑定的消息
/// </summary>
protected void UnBind()
{
UIManager.Instance.Remove(list.ToArray(), this);
list.Clear();
}
/// <summary>
/// 自动移除绑定的消息
/// </summary>
public virtual void OnDestroy()
{
if (list != null)
UnBind();
}
/// <summary>
/// 发消息
/// </summary>
/// <param name="areaCode">Area code.</param>
/// <param name="eventCode">Event code.</param>
/// <param name="message">Message.</param>
public void Dispatch(int areaCode, int eventCode, object message)
{
MsgCenter.Instance.Dispatch(areaCode, eventCode, message);
}
/// <summary>
/// 设置面板显示
/// </summary>
/// <param name="active"></param>
protected void setPanelActive(bool active)
{
gameObject.SetActive(active);
}
}
单例UIManager负责消息的注册和移除 因为UIManager继承自ManagerBase
public class UIManager : ManagerBase
{
public static UIManager Instance = null;
void Awake()
{
Instance = this;
}
}
之后的有关UI操作都是在UIBase派生类上的开发