Unity 游戏框架搭建 (五) 简易消息机制

来源:互联网 发布:linux域名绑定公网ip 编辑:程序博客网 时间:2024/05/29 12:36

什么是消息机制?

23333333,让我先笑一会。

为什么用消息机制?

  三个字,解!!!!耦!!!!合!!!!。

我的框架中的消息机制用例:

1.接收者

using UnityEngine;  using System.Collections;using QFramework;/// <summary>/// 1.接收者需要实现IMsgReceiver接口。/// 2.使用this.RegisterLogicMsg注册消息和回调函数。/// </summary>public class Receiver : MonoBehaviour,IMsgReceiver {    void Awake()    {        this.RegisterLogicMsg ("Receiver Show Sth", ReceiverMsg);//        this.UnRegisterLogicMsg ("Receiver Show Sth", ReceiverMsg);    }    void ReceiverMsg(params object[] paramList)    {        foreach (var sth in paramList) {            QPrint.Warn (sth.ToString());        }    }}

2.发送者

using UnityEngine;  using System.Collections;  using QFramework;/// <summary>/// 1.发送者需要,实现IMsgSender接口/// 2.调用this.SendLogicMsg发送Receiver Show Sth消息,并传入两个参数/// </summary>public class Sender : MonoBehaviour,IMsgSender {    // Update is called once per frame    void Update () {        this.SendLogicMsg ("Receiver Show Sth","你好","世界");    }}

3.运行结果 
使用起来几行代码的事情,实现起来就没这么简单了。

如何实现的?

  可以看到接收者实现了接口IMsgReceiver,发送者实现了接口IMsgSender。 那先看下这两个接口定义。
IMsgReceiver:

using UnityEngine;  using System.Collections;namespace QFramework {    public interface IMsgReceiver  {    }}

IMsgSender

using UnityEngine;  using System.Collections;namespace QFramework {    public interface IMsgSender  {    }}

毛都没有啊。也没有SendLogicMsg或者ReceiveLogicMsg方法的定义啊。

答案是使用C# this的扩展方式实现接口方法。 不清楚的童鞋请百度C# this扩展,有好多文章就不介绍了。 以上先告一段落,先介绍个重要的角色,MsgDispatcher(消息分发器)。

贴上第一部分代码:

namespace QFramework {      /// <summary>    /// 消息分发器    /// C# this扩展 需要静态类    /// </summary>    public static class QMsgDispatcher  {        /// <summary>        /// 消息捕捉器        /// </summary>        class LogicMsgHandler {            public IMsgReceiver receiver;            public  VoidDelegate.WithParams callback;            /*             * VoidDelegate.WithParams 是一种委托 ,定义是这样的              *              *  public class VoidDelegate{             *      public delegate void WithParams(params object[] paramList);             *  }             */            public LogicMsgHandler(IMsgReceiver receiver,VoidDelegate.WithParams callback)            {                this.receiver = receiver;                this.callback = callback;            }        }        /// <summary>        /// 每个消息名字维护一组消息捕捉器。        /// </summary>        static Dictionary<string,List<LogicMsgHandler>> mMsgHandlerDict = new Dictionary<string,List<LogicMsgHandler>> ();

读注释!!!

贴上注册消息的代码

        /// <summary>        /// 注册消息,        /// 注意第一个参数,使用了C# this的扩展,        /// 所以只有实现IMsgReceiver的对象才能调用此方法        /// </summary>        public static void RegisterLogicMsg(this IMsgReceiver self, string msgName,VoidDelegate.WithParams callback)        {            // 略过            if (string.IsNullOrEmpty(msgName)) {                QPrint.FrameworkWarn("RegisterMsg:" + msgName + " is Null or Empty");                return;            }            // 略过            if (null == callback) {                QPrint.FrameworkWarn ("RegisterMsg:" + msgName + " callback is Null");                return;            }            // 略过            if (!mMsgHandlerDict.ContainsKey (msgName)) {                mMsgHandlerDict [msgName] = new List<LogicMsgHandler> ();            }            // 看下这里            var handlers = mMsgHandlerDict [msgName];            // 略过            // 防止重复注册            foreach (var handler in handlers) {                if (handler.receiver == self && handler.callback == callback) {                    QPrint.FrameworkWarn ("RegisterMsg:" + msgName + " ayready Register");                    return;                }            }            // 再看下这里            handlers.Add (new LogicMsgHandler (self, callback));        }

为了节省您时间,略过部分的代码就不要看了,什么?!!你都看了!!!! 23333

发送消息相关的代码

        /// <summary>        /// 发送消息        /// 注意第一个参数        /// </summary>        public static void SendLogicMsg(this IMsgSender sender, string msgName,params object[] paramList )        {            // 略过,不用看            if (string.IsNullOrEmpty(msgName)) {                QPrint.FrameworkError("SendMsg is Null or Empty");                return;            }             // 略过,不用看            if (!mMsgHandlerDict.ContainsKey(msgName)){                QPrint.FrameworkWarn("SendMsg is UnRegister");                return;            }            // 开始看!!!!            var handlers = mMsgHandlerDict[msgName];            var handlerCount = handlers.Count;            // 之所以是从后向前遍历,是因为  从前向后遍历删除后索引值会不断变化            // 参考文章,http://www.2cto.com/kf/201312/266723.html            for (int index = handlerCount - 1;index >= 0;index--)            {                var handler = handlers[index];                if (handler.receiver != null) {                    QPrint.FrameworkLog ("SendLogicMsg:" + msgName + " Succeed");                    handler.callback (paramList);                } else {                    handlers.Remove (handler);                }            }        }

OK主要的部分全都贴出来啦 
以上代码以全部上传到Github上边
贴出代码地址:消息机制相关代码地址

可以改进的地方:

  1.目前整个游戏的消息都由一个字典维护,可以改进为每个模块维护一个字典或者其他方式。   2.消息名字类型由字符串定义的,可以改成枚举转unsigned int方式。   3.欢迎补充。

  1.如果是MonoBehaviour注册消息之后,GameObject Destroy之前一定要注销消息,之前的解决方案是,自定义一个基类来维护该对象已经注册的消息列表,然后在基类的OnDestory时候遍历卸载。   2.欢迎补充。

阅读全文
0 0
原创粉丝点击