Unity 游戲框架搭建 2017 (五) 簡易消息機制


 

什么是消息機制?

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

23333333,讓我先笑一會。

為什么用消息機制?

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

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

1.接收者 Receiver.cs

using UnityEngine; namespace QFramework.Example { /// <summary> /// 教程地址:http://liangxiegame.com/post/5/ /// </summary> public class Receiver : MonoBehaviour, IMsgReceiver { // Use this for initialization private void Awake() { this.RegisterLogicMsg("Receiver Show Sth", ReceiveMsg); } private void ReceiveMsg(object[] args) { foreach (var arg in args) { Log.I(arg); } } } }

2.發送者

using UnityEngine; namespace QFramework.Example { /// <summary> /// 教程地址:http://liangxiegame.com/post/5/ /// </summary> public class Sender : MonoBehaviour, IMsgSender { void Update() { this.SendLogicMsg("Receiver Show Sth", "你好", "世界"); } } } 

3.運行結果

 

 

使用起來幾行代碼的事情,實現起來就沒這么簡單了。

如何實現的?

可以看到接收者實現了接口IMsgReceiver,發送者實現了接口 IMsgSender。 那先看下這兩個接口定義。

IMsgReceiver.cs:

namespace QFramework 
{
    public interface IMsgReceiver { } }

IMsgSender.cs:

namespace QFramework 
{
    public interface IMsgSender { } }

毛都沒有啊。也沒有 SendLogicMsg 或者 ReceiveLogicMsg 方法的定義啊。

答案是使用 C# this 的擴展方式實現接口方法。

不清楚的童鞋請百度 C# this 擴展,有好多文章就不介紹了。

以上先告一段落,先介紹個重要的角色,MsgDispatcher (消息分發器)。

貼上第一部分代碼:

    /// <summary> /// 消息分發器 /// C# this擴展 需要靜態類 /// 教程地址:http://liangxiegame.com/post/5/ public static class MsgDispatcher { /// <summary> /// 消息捕捉器 /// </summary> private class LogicMsgHandler { public readonly IMsgReceiver Receiver; public readonly Action<object[]> Callback; public LogicMsgHandler(IMsgReceiver receiver, Action<object[]> callback) { Receiver = receiver; Callback = callback; } } /// <summary> /// 每個消息名字維護一組消息捕捉器。 /// </summary> static readonly Dictionary<string, List<LogicMsgHandler>> mMsgHandlerDict = new Dictionary<string, List<LogicMsgHandler>>();

讀注釋!!!

貼上注冊消息的代碼

        /// <summary> /// 注冊消息, /// 注意第一個參數,使用了C# this的擴展, /// 所以只有實現IMsgReceiver的對象才能調用此方法 /// </summary> public static void RegisterLogicMsg(this IMsgReceiver self, string msgName, Action<object[]> callback) { // 略過 if (string.IsNullOrEmpty(msgName)) { Log.W("RegisterMsg:" + msgName + " is Null or Empty"); return; } // 略過 if (null == callback) { Log.W("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) { Log.W("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)) { Log.E("SendMsg is Null or Empty"); return; } // 略過,不用看 if (!mMsgHandlerDict.ContainsKey(msgName)) { Log.W("SendMsg is UnRegister"); return; } // 開始看!!!! var handlers = mMsgHandlerDict[msgName]; var handlerCount = handlers.Count; // 之所以是從后向前遍歷,是因為 從前向后遍歷刪除后索引值會不斷變化 // 參考文章,http://www.2cto.com/kf/201312/266723.html for (var index = handlerCount - 1; index >= 0; index--) { var handler = handlers[index]; if (handler.Receiver != null) { Log.W("SendLogicMsg:" + msgName + " Succeed"); handler.Callback(paramList); } else { handlers.Remove(handler); } } }

OK 主要的部分全都貼出來啦。

可以改進的地方:

  • 目前整個游戲的消息都由一個字典維護,可以改進為每個模塊維護一個字典或者其他方式。
  • 消息名字類型由字符串定義的,可以改成枚舉轉 unsigned int 方式。
  • 歡迎補充。

坑:

  • 如果是 MonoBehaviour 注冊消息之后,GameObject Destroy 之前一定要注銷消息,之前的解決方案是,自定義一個基類來維護該對象已經注冊的消息列表,然后在基類的 OnDestory 時候遍歷卸載。
  • 歡迎補充。

轉載請注明地址:涼鞋的筆記:liangxiegame.com

更多內容


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM