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 游戏框架搭建】
前言 架构和框架这些概念听起来很遥远,让很多初学者不明觉厉.会产生"等自己技术牛逼了再去做架构或者搭建框架"这样的想法.在这里笔者可以很肯定地告诉大家,初学者是完全可以去做这些事情 ...
随机推荐
- 欧拉函数之HDU1286找新朋友
找新朋友 Time Limit : 2000/1000ms (Java/Other) Memory Limit : 65536/32768K (Java/Other) Total Submissi ...
- JSP servlet的配置与使用
1. servlet 的配置文件内容如下所示 <servlet> <description>This is the description of my J2EE com ...
- 3、J2EE学习推荐书籍
3.J2EE学习推荐书籍 J2EE的学习应该循序渐进,一本好书会很快上手和深入.在学习J2EE之前,应该学好SQL,基本上,程序设计都会跟数据库打交道.如果SQL没学好,就如同房子没有基脚 ...
- 重构了cxlt-vue2-toastr插件
距离上篇文章已经过去一个多月了,期间有很多想法,但时间真不是想挤就能挤出来的.其实这段时间我就做了一件事,一个小程序的项目,已上线半月有余,也迭代了几个版本,现在还在不断完善. 先说点题外话,我们做了 ...
- python 收录集中实现线程池的方法
概念: 什么是线程池? 诸如web服务器.数据库服务器.文件服务器和邮件服务器等许多服务器应用都面向处理来自某些远程来源的大量短小的任务.构建服务器应用程序的一个过于简单的模型是:每当一个请求到达就创 ...
- Day1 - Python基础1 Python介绍、基本语法、流程控制习题集
1.打印Hello World! print("Hello World!") 或 name="你好,世界!" print(name) 2.声明变量:打印name ...
- win10下面visual studio, sublime ctrl+shift+f快捷键失效的原因
在visual studio 和sublime中,经常遇到ctrl+shift+f不能用,然后输入法总是自动切换成繁体中文. 实在百思不得其解. 今天才发现,我用的windows 10自带的微软拼音输 ...
- 封装TableView有可能用到的数据结构和UITableViewCell的一个继承类
最近4年的时间,我已经做了5个App完全独立开发, 工作经历5个App, 维护了两个App. 在这期间用的最多的是UITableView, 因此也有许多感觉可以封装的. 现在就是我封装的. RXCel ...
- windows手动搭建Kotlin命令行环境
kotlin官网:https://kotlinlang.org 我们可以从GitHub下载.目前最新版本是1.1.2-5 https://github.com/JetBrains/kotlin/rel ...
- 判断客户端使用的是安卓还是苹果,然后加载对应的css文件
<script type="text/javascript" charset="utf-8"> var browser = { versions: ...