Unity 游戲框架搭建 (五) 簡(jiǎn)易消息機(jī)制
來(lái)源:
未知 |
責(zé)任編輯:駱駝祥子 |
發(fā)布時(shí)間: 2017-07-05 14:43 | 瀏覽量:
本節(jié)匯寶盆為大家?guī)?lái)unity3d的游戲框架搭建(五)簡(jiǎn)易消息機(jī)制
感謝涼鞋的筆記的分享,更多精彩內(nèi)容盡在匯寶盆!
3d素材Unity 游戲框架搭建 (一) 概述 | http://studio-ampersand.com/club/thread-403704-1.html |
3d素材unity 游戲框架搭建 (二) 單例的模板 | http://studio-ampersand.com/club/thread-403705-1.html |
3d素材unity游戲框架搭建 (三) MonoBehaviour單例的模板 | http://studio-ampersand.com/club/thread-403706-1.html |
3d素材unity 游戲框架搭建 (四) 簡(jiǎn)易有限狀態(tài)機(jī) | http://studio-ampersand.com/club/thread-403707-1.html |
什么是消息機(jī)制?
為什么用消息機(jī)制?
三個(gè)字,解!!!!耦!!!!合!!!!。
我的框架中的消息機(jī)制用例:
1.接收者
using UnityEngine;
using System.Collections;
using QFramework;
/// <summary>
/// 1.接收者需要實(shí)現(xiàn)IMsgReceiver接口。
/// 2.使用this.RegisterLogicMsg注冊(cè)消息和回調(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ā)送者需要,實(shí)現(xiàn)IMsgSender接口
/// 2.調(diào)用this.SendLogicMsg發(fā)送Receiver Show Sth消息,并傳入兩個(gè)參數(shù)
/// </summary>
public class Sender : MonoBehaviour,IMsgSender {
// Update is called once per frame
void Update () {
this.SendLogicMsg ("Receiver Show Sth","你好","世界");
}
}
3.運(yùn)行結(jié)果
使用起來(lái)幾行代碼的事情,實(shí)現(xiàn)起來(lái)就沒(méi)這么簡(jiǎn)單了。
如何實(shí)現(xiàn)的?
可以看到接收者實(shí)現(xiàn)了接口IMsgReceiver,發(fā)送者實(shí)現(xiàn)了接口IMsgSender。 那先看下這兩個(gè)接口定義。
IMsgReceiver:
using UnityEngine;
using System.Collections;
namespace QFramework {
public interface IMsgReceiver {
}
}
IMsgSender
using UnityEngine;
using System.Collections;
namespace QFramework {
public interface IMsgSender {
}
}
毛都沒(méi)有啊。也沒(méi)有SendLogicMsg或者ReceiveLogicMsg方法的定義啊。
答案是使用C# this的擴(kuò)展方式實(shí)現(xiàn)接口方法。 不清楚的童鞋請(qǐng)百度C# this擴(kuò)展,有好多文章就不介紹了。 以上先告一段落,先介紹個(gè)重要的角色,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>
/// 每個(gè)消息名字維護(hù)一組消息捕捉器。
/// </summary>
static Dictionary<string,List<LogicMsgHandler>> mMsgHandlerDict = new Dictionary<string,List<LogicMsgHandler>> ();
讀注釋!!!
貼上注冊(cè)消息的代碼
/// <summary>
/// 注冊(cè)消息,
/// 注意第一個(gè)參數(shù),使用了C# this的擴(kuò)展,
/// 所以只有實(shí)現(xiàn)IMsgReceiver的對(duì)象才能調(diào)用此方法
/// </summary>
public static void RegisterLogicMsg(this IMsgReceiver self, string msgName,VoidDelegate.WithParams callback)
{
// 略過(guò)
if (string.IsNullOrEmpty(msgName)) {
QPrint.FrameworkWarn("RegisterMsg:" + msgName + " is Null or Empty");
return;
}
// 略過(guò)
if (null == callback) {
QPrint.FrameworkWarn ("RegisterMsg:" + msgName + " callback is Null");
return;
}
// 略過(guò)
if (!mMsgHandlerDict.ContainsKey (msgName)) {
mMsgHandlerDict [msgName] = new List<LogicMsgHandler> ();
}
// 看下這里
var handlers = mMsgHandlerDict [msgName];
// 略過(guò)
// 防止重復(fù)注冊(cè)
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ā)送消息
/// 注意第一個(gè)參數(shù)
/// </summary>
public static void SendLogicMsg(this IMsgSender sender, string msgName,params object[] paramList )
{
// 略過(guò),不用看
if (string.IsNullOrEmpty(msgName)) {
QPrint.FrameworkError("SendMsg is Null or Empty");
return;
}
// 略過(guò),不用看
if (!mMsgHandlerDict.ContainsKey(msgName)){
QPrint.FrameworkWarn("SendMsg is UnRegister");
return;
}
// 開(kāi)始看!!!!
var handlers = mMsgHandlerDict[msgName];
var handlerCount = handlers.Count;
// 之所以是從后向前遍歷,是因?yàn)?nbsp; 從前向后遍歷刪除后索引值會(huì)不斷變化
// 參考文章,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主要的部分全都貼出來(lái)啦
以上代碼以全部上傳到論壇上邊
貼出代碼地址:消息機(jī)制相關(guān)代碼地址
可以改進(jìn)的地方:
1.目前整個(gè)游戲的消息都由一個(gè)字典維護(hù),可以改進(jìn)為每個(gè)模塊維護(hù)一個(gè)字典或者其他方式。 2.消息名字類型由字符串定義的,可以改成枚舉轉(zhuǎn)unsigned int方式。 3.歡迎補(bǔ)充。
坑
1.如果是MonoBehaviour注冊(cè)消息之后,GameObject Destroy之前一定要注銷消息,之前的解決方案是,自定義一個(gè)基類來(lái)維護(hù)該對(duì)象已經(jīng)注冊(cè)的消息列表,然后在基類的OnDestory時(shí)候遍歷卸載。 2.歡迎補(bǔ)充。
感謝涼鞋的筆記的分享,更多精彩內(nèi)容盡在匯寶盆!
- Tags:Unity教程
-
分享到:
相關(guān)文章
網(wǎng)友評(píng)論
您需要登錄后才可以發(fā)帖 登錄 | 立即注冊(cè)
關(guān)閉
- 用戶名:
- 密 碼:
- 驗(yàn)證碼: 看不清? 點(diǎn)擊更換
- 忘記密碼?
全部評(píng)論:1條
推薦
熱門