? 爽爽婬人综合网网站,直接看的成人无码视频网站
聯(lián)系我們

給我們留言

聯(lián)系我們

地址:福建省晉江市青陽街道洪山路國際工業(yè)設(shè)計園納金網(wǎng)

郵箱:info@narkii.com

電話:0595-82682267

(周一到周五, 周六周日休息)

當(dāng)前位置:主頁 > 3D教程 > 圖文教程

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

來源: 未知 | 責(zé)任編輯:駱駝祥子 | 發(fā)布時間: 2017-07-05 14:43 | 瀏覽量:
本節(jié)匯寶盆為大家?guī)韚nity3d的游戲框架搭建(五)簡易消息機(jī)制

3d素材Unity 游戲框架搭建 (一) 概述 http://594ljc.cn/club/thread-403704-1.html
3d素材unity 游戲框架搭建 (二) 單例的模板 http://594ljc.cn/club/thread-403705-1.html
3d素材unity游戲框架搭建 (三) MonoBehaviour單例的模板 http://594ljc.cn/club/thread-403706-1.html
3d素材unity 游戲框架搭建 (四) 簡易有限狀態(tài)機(jī) http://594ljc.cn/club/thread-403707-1.html


什么是消息機(jī)制?
Unity 游戲框架搭建 (五) 簡易消息機(jī)制
Unity 游戲框架搭建 (五) 簡易消息機(jī)制
Unity 游戲框架搭建 (五) 簡易消息機(jī)制
Unity 游戲框架搭建 (五) 簡易消息機(jī)制
Unity 游戲框架搭建 (五) 簡易消息機(jī)制

為什么用消息機(jī)制?
  
三個字,解!!!!耦!!!!合!!!!。

我的框架中的消息機(jī)制用例:

1.接收者

using UnityEngine; 
using System.Collections;

using QFramework;

/// <summary>
/// 1.接收者需要實現(xiàn)IMsgReceiver接口。
/// 2.使用this.RegisterLogicMsg注冊消息和回調(diào)函數(shù)。
/// </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.發(fā)送者

using UnityEngine; 
using System.Collections; 
using QFramework;

/// <summary>
/// 1.發(fā)送者需要,實現(xiàn)IMsgSender接口
/// 2.調(diào)用this.SendLogicMsg發(fā)送Receiver Show Sth消息,并傳入兩個參數(shù)
/// </summary>
public class Sender : MonoBehaviour,IMsgSender {

    // Update is called once per frame
    void Update () {
        this.SendLogicMsg ("Receiver Show Sth","你好","世界");
    }
}
3.運行結(jié)果
Unity 游戲框架搭建 (五) 簡易消息機(jī)制
使用起來幾行代碼的事情,實現(xiàn)起來就沒這么簡單了。

如何實現(xiàn)的?
  可以看到接收者實現(xiàn)了接口IMsgReceiver,發(fā)送者實現(xiàn)了接口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的擴(kuò)展方式實現(xiàn)接口方法。 不清楚的童鞋請百度C# this擴(kuò)展,有好多文章就不介紹了。 以上先告一段落,先介紹個重要的角色,MsgDispatcher(消息分發(fā)器)。

貼上第一部分代碼:

namespace QFramework { 
    /// <summary>
    /// 消息分發(fā)器
    /// C# this擴(kuò)展 需要靜態(tài)類
    /// </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>
        /// 每個消息名字維護(hù)一組消息捕捉器。
        /// </summary>
        static Dictionary<string,List<LogicMsgHandler>> mMsgHandlerDict = new Dictionary<string,List<LogicMsgHandler>> ();
讀注釋!!!

貼上注冊消息的代碼

        /// <summary>
        /// 注冊消息,
        /// 注意第一個參數(shù),使用了C# this的擴(kuò)展,
        /// 所以只有實現(xiàn)IMsgReceiver的對象才能調(diào)用此方法
        /// </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];

            // 略過
            // 防止重復(fù)注冊
            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));
        }


發(fā)送消息相關(guān)的代碼

        /// <summary>
        /// 發(fā)送消息
        /// 注意第一個參數(shù)
        /// </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主要的部分全都貼出來啦
以上代碼以全部上傳到論壇上邊
貼出代碼地址:消息機(jī)制相關(guān)代碼地址

可以改進(jìn)的地方:

  1.目前整個游戲的消息都由一個字典維護(hù),可以改進(jìn)為每個模塊維護(hù)一個字典或者其他方式。   2.消息名字類型由字符串定義的,可以改成枚舉轉(zhuǎn)unsigned int方式。   3.歡迎補充。



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


感謝涼鞋的筆記的分享,更多精彩內(nèi)容盡在匯寶盆

相關(guān)文章
網(wǎng)友評論

您需要登錄后才可以發(fā)帖 登錄 | 立即注冊

關(guān)閉

全部評論:1條

推薦
熱門