Unity框架设计(一) 消息处理框架

来源:互联网 发布:网络歌手萧风 编辑:程序博客网 时间:2024/06/06 07:32

Unity框架设计(一) 消息处理框架

关于Unity的原生消息机制

为了降低耦和,Unity自带了消息机制。主要体现在如下三个方法:
SendMessage, SendMessageUpwards, BroadcastMessage
但是我们平时几乎不会使用它们,主要有如下几点缺陷:
1. 内部使用反射,性能较差
2. 严重依赖字符串,无法在编译阶段实现类型安全
3. 只有继承自MonoBehaviour才可以调用
4. 可以调用私有方法,破坏封装性
所以开发游戏过程中构建一套自己的消息处理机制是必不可少的

实现自己的消息处理框架

那么现在可以针对这些缺陷去实现自己的消息处理框架了,基于C#的委托去实现,性能上和安全性上都远远强过Unity的原生消息传递机制。

一般来讲我不喜欢使用单例模式实现除非逼不得已,因为不容易控制单例的生存周期,很难有一个合理的初始化顺序。同时为了兼顾易用性和安全性,所以我们使用泛型静态类来实现

首先写一个异常,抛出该框架内部的异常

public class MessageException : Exception {        public MessageException(string message, Exception innerException) : base(message, innerException) { }        public MessageException(string message):base(message) { }        public MessageException() : base() { }}

接下来是框架部分

namespace ZCC.MessageCenter {    /// <summary>消息中心的异常</summary>    public class MessageException : Exception {        public MessageException(string message, Exception innerException) : base(message, innerException) { }        public MessageException(string message):base(message) { }        public MessageException() : base() { }    }    /// <summary>消息中心</summary>    /// <typeparam name="TMessage">消息枚举 每种类型的消息枚举都有一个消息中心</typeparam>    public static class MessageCenter<TMessage> where TMessage: struct {        /// <summary>已注册的消息字典</summary>        private static Dictionary<TMessage, EventHandler> _dicMessages = new Dictionary<TMessage, EventHandler>();        /// <summary>向某消息注册监听者 </summary>        public static void AddListener(TMessage message, EventHandler messageHandler) {            if (!_dicMessages.ContainsKey(message))                _dicMessages.Add(message, null);            _dicMessages[message] += messageHandler;        }        /// <summary>注销某消息的某个监听者 </summary>        public static void RemoveListener(TMessage message, EventHandler messageHandler) {            if (!_dicMessages.ContainsKey(message)) {                Debug.LogError(typeof(TMessage).Name + ":" + "[RemoveListener]不存在此messageKey:[" + message.ToString() + "]");                return;            }            _dicMessages[message] -= messageHandler;        }        /// <summary>发送消息给所有监听者</summary>        public static void SendMessage(TMessage message, object sender, EventArgs eventArgs) {            if (!_dicMessages.ContainsKey(message)) {                Debug.LogError(typeof(TMessage).Name+":"+"[SendMessage]不存在此messageKey:["+ message.ToString()+"]");                return;            }            Delegate[] invocationList = _dicMessages[message].GetInvocationList();            foreach (Delegate invocation in invocationList) {                try {                    (invocation as EventHandler)(sender, eventArgs);                }                catch(Exception e) {                    Debug.LogError(e);                    throw e;                }            }        }    }}

TMessage作为泛型参数,被限定为值类型,使用枚举作为一类消息的标识,代码看起来可读性很高。不同的类型参数有自己的消息字典,维护各自内部的消息处理。 比如为了传递UI消息,我们先设计一个UIMessage枚举,用来枚举所有UI消息

public enum UIMessage {    /// <summary></summary>    ENull = 0,    /// <summary>打开窗口<summary>    OpenForm = 1,    /// <summary>关闭窗口<summary>    CloseForm = 2}

然后针对自己的业务逻辑设计传递的消息类,该类需要继承自EventArgs

public class UIEventArgs: EventArgs{    public string FormName;    public UIEventArgs(string formName){            this.FormName = formName;    }}

具体用法也不必赘述了, 下面写一个小例子

public class Example: MonoBehaviour {    private void Awake( ){          //向OpenForm注册监听者        MessageCenter<UIMessage>.AddListener(UIMessage.OpenForm, OnOpenForm);        //向所有注册OpenForm的监听者发送消息        MessageCenter<UIMessage>.SendMessage(UIMessage.OpenForm,new UIEventArgs("LoginForm"));    }    private void OnOpenForm(object sender, this, EventArgs eventArgs){        print("打开窗口"+(eventArgs as UIEventArgs).FormName);    }}

当然还有一些地方可以扩展改进,欢迎留言!

原创粉丝点击