您的位置:首页 > 移动开发 > Unity3D

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

2017-11-07 09:22 519 查看

什么是消息机制?











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;

///

/// 1.发送者需要,实现IMsgSender接口

/// 2.调用this.SendLogicMsg发送Receiver Show Sth消息,并传入两个参数

///

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 {

///

/// 消息分发器

/// C# this扩展 需要静态类

///

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上边
贴出代码地址:[消息机制相关代码地址](https://github.com/liangxiegame/QFramework/tree/master/Script/Event)

#### 可以改进的地方:

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

#### 坑

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

附:[我的框架QFramework地址](https://github.com/liangxiegame/QFramework)

[单例库QSingleton地址](https://github.com/liangxiegame/QFramework)

转载请注明地址:[凉鞋的笔记](http://liangxiegame.com/)

微信公众号:liangxiegame

![](http://liangxiegame.com/content/images/2017/06/qrcode_for_gh_32f0f3669ac8_430.jpg)

#output/writing/unity游戏框架搭建
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: