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

什麼是消息機制?

23333333,讓我先笑一會。

為什麼用消息機制?

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

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

1.接收者

using UnityEngine;nusing System.Collections;nnusing QFramework;nn/// <summary>n/// 1.接收者需要實現IMsgReceiver介面。n/// 2.使用this.RegisterLogicMsg註冊消息和回調函數。n/// </summary>npublic class Receiver : MonoBehaviour,IMsgReceiver {nn void Awake()n {n this.RegisterLogicMsg ("Receiver Show Sth", ReceiverMsg);nn// this.UnRegisterLogicMsg ("Receiver Show Sth", ReceiverMsg);nn }nnn void ReceiverMsg(params object[] paramList)n {n foreach (var sth in paramList) {n QPrint.Warn (sth.ToString());n }n }n}n

2.發送者

using UnityEngine;nusing System.Collections;nusing QFramework;nn/// <summary>n/// 1.發送者需要,實現IMsgSender介面n/// 2.調用this.SendLogicMsg發送Receiver Show Sth消息,並傳入兩個參數n/// </summary>npublic class Sender : MonoBehaviour,IMsgSender {nn // Update is called once per framen void Update () {n this.SendLogicMsg ("Receiver Show Sth","你好","世界");n }n}n

3.運行結果

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

如何實現的?

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

IMsgReceiver:nusing UnityEngine;nusing System.Collections;nnnamespace QFramework {nn public interface IMsgReceiver {nnn }n}n

IMsgSender

using UnityEngine;nusing System.Collections;nnnamespace QFramework {nn public interface IMsgSender {nn }n}n

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

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

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

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

貼上第一部分代碼:

namespace QFramework {n /// <summary>n /// 消息分發器n /// C# this擴展 需要靜態類n /// </summary>n public static class QMsgDispatcher {nn /// <summary>n /// 消息捕捉器n /// </summary>n class LogicMsgHandler {nn public IMsgReceiver receiver;n public VoidDelegate.WithParams callback;nn /*n * VoidDelegate.WithParams 是一種委託 ,定義是這樣的 n * n * public class VoidDelegate{n * public delegate void WithParams(params object[] paramList);n * }n */n public LogicMsgHandler(IMsgReceiver receiver,VoidDelegate.WithParams callback)n {n this.receiver = receiver;n this.callback = callback;n }n }nn /// <summary>n /// 每個消息名字維護一組消息捕捉器。n /// </summary>n static Dictionary<string,List<LogicMsgHandler>> mMsgHandlerDict = new Dictionary<string,List<LogicMsgHandler>> ();n

讀注釋!!!

貼上註冊消息的代碼

/// <summary>n /// 註冊消息,n /// 注意第一個參數,使用了C# this的擴展,n /// 所以只有實現IMsgReceiver的對象才能調用此方法n /// </summary>n public static void RegisterLogicMsg(this IMsgReceiver self, string msgName,VoidDelegate.WithParams callback)n {n // 略過n if (string.IsNullOrEmpty(msgName)) {n QPrint.FrameworkWarn("RegisterMsg:" + msgName + " is Null or Empty");n return;n }nn // 略過n if (null == callback) {n QPrint.FrameworkWarn ("RegisterMsg:" + msgName + " callback is Null");n return;n }nn // 略過n if (!mMsgHandlerDict.ContainsKey (msgName)) {n mMsgHandlerDict [msgName] = new List<LogicMsgHandler> ();n }nn // 看下這裡n var handlers = mMsgHandlerDict [msgName];nn // 略過n // 防止重複註冊n foreach (var handler in handlers) {n if (handler.receiver == self && handler.callback == callback) {n QPrint.FrameworkWarn ("RegisterMsg:" + msgName + " ayready Register");n return;n }n }nn // 再看下這裡n handlers.Add (new LogicMsgHandler (self, callback));n }n

為了節省您時間,略過部分的代碼就不要看了,什麼?!!你都看了!!!! 23333

發送消息相關的代碼

/// <summary>n /// 發送消息n /// 注意第一個參數n /// </summary>n public static void SendLogicMsg(this IMsgSender sender, string msgName,params object[] paramList )n {n // 略過,不用看n if (string.IsNullOrEmpty(msgName)) {n QPrint.FrameworkError("SendMsg is Null or Empty");n return;n } nn // 略過,不用看n if (!mMsgHandlerDict.ContainsKey(msgName)){n QPrint.FrameworkWarn("SendMsg is UnRegister");n return;n }nn // 開始看!!!!n var handlers = mMsgHandlerDict[msgName];nnn var handlerCount = handlers.Count;nn // 之所以是從後向前遍歷,是因為 從前向後遍歷刪除後索引值會不斷變化n // 參考文章,http://www.2cto.com/kf/201312/266723.htmln for (int index = handlerCount - 1;index >= 0;index--)n {n var handler = handlers[index];nn if (handler.receiver != null) {n QPrint.FrameworkLog ("SendLogicMsg:" + msgName + " Succeed");n handler.callback (paramList);n } else {n handlers.Remove (handler);n }n }n }n

OK主要的部分全都貼出來啦 以上代碼以全部上傳到Github上邊 貼出代碼地址:消息機制相關代碼地址

可以改進的地方:

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

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

附:我的框架QFramework地址

單例庫QSingleton地址

轉載請註明地址:涼鞋的筆記

微信公眾號:liangxiegame

weixin.qq.com/r/gjumvif (二維碼自動識別)

output/writing/unity遊戲框架搭建

推薦閱讀:

無為文件管理術之「框架思維」
Retrofit 實現分析
2016年 CSS 庫、框架和工具新生榜 TOP 50
PHP模版引擎,框架有什麼區別,各有什麼用?

TAG:Unity游戏引擎 | 框架 |