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





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
更多内容
QFramework 地址:https://github.com/liangxiegame/QFramework
QQ 交流群:623597263
Unity 进阶小班:
- 主要训练内容:
- 框架搭建训练(第一年)
- 跟着案例学 Shader(第一年)
- 副业的孵化(第二年、第三年)
- 权益、授课形式等具体详情请查看《小班产品手册》:https://liangxiegame.com/master/intro
- 主要训练内容:
关注公众号:liangxiegame 获取第一时间更新通知及更多的免费内容。

Unity 游戏框架搭建 (五) 简易消息机制的更多相关文章
- Unity 游戏框架搭建 (四) 简易有限状态机
为什么用有限状态机? 之前做过一款跑酷游戏,跑酷角色有很多状态:跑.跳.二段跳.死亡等等.一开始是使用if/switch来切换状态,但是每次角色添加一个状态(提前没规划好),所有状态处理相关的代码 ...
- Unity 游戏框架搭建 (十一) 简易AssetBundle打包工具(一)
最近在看Unity官方的AssetBundle(以下简称AB)的教程,也照着做了一遍,不过做出来的AssetBundleManager的API设计得有些不太习惯.目前想到了一个可行的解决方案.AB相关 ...
- Unity 游戏框架搭建 (十) QFramework v0.0.2小结
从框架搭建系列的第一篇文章开始到现在有四个多月时间了,这段时间对自己来说有很多的收获,好多小伙伴和前辈不管是在评论区还是私下里给出的建议非常有参考性,在此先谢过各位. 说到是一篇小节,先列出框架的概要 ...
- Unity 游戏框架搭建 2018 (一) 架构、框架与 QFramework 简介
约定 还记得上版本的第二十四篇的约定嘛?现在出来履行啦~ 为什么要重制? 之前写的专栏都是按照心情写的,在最初的时候笔者什么都不懂,而且文章的发布是按照很随性的一个顺序.结果就是说,大家都看完了,都还 ...
- Unity 游戏框架搭建 (十六) v0.0.1 架构调整
背景: 前段时间用Xamarin.OSX开发一些工具,遇到了两个问题. QFramework的大部分的类耦合了Unity的API,这样导致不能在其他CLR平台使用QFramework. QFramew ...
- Unity 游戏框架搭建 (十三) 无需继承的单例的模板
之前的文章中介绍的Unity 游戏框架搭建 (二) 单例的模板和Unity 游戏框架搭建 (三) MonoBehaviour单例的模板有一些问题. 存在的问题: 只要继承了单例的模板就无法再继承其他的 ...
- Unity 游戏框架搭建 2019 (五十、五十一) 消息机制小结&MonoBehaviourSimplify 是框架?
我们花了 5 篇文章学习了消息机制的方方面面.并且完成了一个简易消息机制,之后集成到了我们的 MonoBehaviourSimplify 里. 现在 MonoBehaviourSimplify 有一点 ...
- Unity 游戏框架搭建 2019 (四十六) 简易消息机制 & 集成到 MonoBehaviourSimplify 里
在上一篇,我们接触了单例,使用单例解决了我们脚本之间访问的问题. 脚本之间访问其实有更好的方式. 我们先分下脚本访问脚本的几种形式. 第一种,A GameObject 是 B GameObject 的 ...
- 凉鞋:我所理解的框架 【Unity 游戏框架搭建】
前言 架构和框架这些概念听起来很遥远,让很多初学者不明觉厉.会产生"等自己技术牛逼了再去做架构或者搭建框架"这样的想法.在这里笔者可以很肯定地告诉大家,初学者是完全可以去做这些事情 ...
随机推荐
- Natas Wargame Level20 Writeup(会话状态注入/篡改)
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAArMAAACmCAYAAADJYwcaAAAABHNCSVQICAgIfAhkiAAAIABJREFUeF
- h5分享页面打开APP
项目中 直播app分享出来的直播h5页面 点击进入按钮:已下载app 就进入app,未下载跳转到下载页面 判断是安卓还是ios var u = navigator.userAgent; var isA ...
- MyBatis 3 User Guide Simplified Chinese.pdf
MyBatis 3 用户指南 帮助我们把文档做得更好… 如果你发现了本文档的遗漏之处,或者丢失 MyBatis 特性的说明时,那么最好的方法就 是了解一下这个遗漏之处然后把它记录下来. 我们在 wik ...
- 【Netty】Netty之ByteBuf
一.前言 前面已经学习了Netty中传输部分,现在接着学习Netty中的ByteBuf. 二.ByteBuf 2.1 ByteBuf API 在网络上传输的数据形式为Byte,Java NIO提供了B ...
- Swift 入门之简单语法(三)
集合 数组 数组使用 [] 定义,这一点与 OC 相同 //: [Int] let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 遍历 for num in nu ...
- python3 爬 妹子图
Beautiful Soup 是一个可以从HTML或XML文件中提取数据的Python库.它能够通过你喜欢的转换器实现惯用的文档导航,查找,修改文档的方式 Beautiful Soup 4 通过PyP ...
- zabbix agent安装详解
安装 Installing repository configuration package Zabbix 2.2 for RHEL5, Oracle Linux 5, CentOS 5: rpm - ...
- python 2.7中urllib 2 与python 3.5中 urllib的区别。
python 3.x中urllib库和urilib2库合并成了urllib库. 其中urllib2.urlopen()变成了urllib.request.urlopen() urllib2.Reque ...
- Python教程(2.4)——字符串
2.2节讲过,Python中有字符串类型.在Python中,字符串用'或"括起,例如'abc'."qwerty"等都是字符串.注意'和"并不是字符串的内容. A ...
- [深圳/广州]微软SQL技术沙龙分享会(MVP)
[深圳/广州] 新一期俱乐部活动报名开始,这次是广深地区SQL Server 技术沙龙分享会(MVP),SQL Server作为一个数据平台,不管是SQL Server 2017 on Linux 还 ...