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 游戏框架搭建】
前言 架构和框架这些概念听起来很遥远,让很多初学者不明觉厉.会产生"等自己技术牛逼了再去做架构或者搭建框架"这样的想法.在这里笔者可以很肯定地告诉大家,初学者是完全可以去做这些事情 ...
随机推荐
- 【flex弹性盒布局】------这个强大的功能
你知道flex弹性布局么? 我们先来了解它的概念:Flex是Flexible Box的缩写,意为"弹性布局",用来为盒状模型提供最大的灵活性. 任何一个容器都可以指定为Flex布局 ...
- NodeJS 入门第二天(EJS模板)
一.复习 复习:Node.js开发服务器,数据.路由.本地关心的效果,交互: Node.js实际上是极客开发出的一个小玩具,不是银弹.有着别人不具备的怪异特点: 单线程.Non-blocking I/ ...
- (HTTPS)-tomcat 实现 https 登录,去掉端口号
最近项目组要给日本客户做个产品,升级服务器交由我来升级.为了测试用,想要在自己电脑上搭个服务器. 服务器需要由https登录,并且不显示端口号. 费了些劲儿,看了n多帖子,好不容易弄好了.趁在没忘记之 ...
- 未能加载文件或程序集Newtonsoft.Json, Version=4.5.0.0
1.打开 程序管理器控制台 输入 PM> install-package newtonsoft.json 2.查看bin文件中是否有 newtonsoft.json.dll文件 3.在Web. ...
- MysqlRouter 实现mysql5.6读写分离
下载,安装 [root@localhost src]# cd /usr/local/src/ [root@localhost src]# wget http://dev.mysql.com/get ...
- 汽车Vin码识别技术的由来到发展
核心内容:汽车Vin码.汽车车架号.Vin码识别.汽车Vin码识别.车架号识别.汽车车架号识别 一.汽车Vin码识别应用背景 随着二手车产业链发展越来越强大,在汽车买卖以及后市场应用中,了解车辆的相关 ...
- 数据库插入数据失败,log提示不能将值 NULL 插入列 'id'
已经记不住具体的log信息了,意思就是ID如果没有设置为自增长的情况下就不能插入数据,而建表时ID字段是设置为"not null",所以就不能顺利插入数据. 解决方法有两种: ①建 ...
- Java IO流之内存流
内存流 1)内存流主要用来操作内存 2)分类 ByteArrayInputStream 主要完成将内容从内存读入程序之中 ByteArrayOutputStream 主要是将数据写入到内存中. 3)输 ...
- 新手如何快速入门Python
学习任何一门语言都是从入门(1年左右),通过不间断练习达到熟练水准(3到5年),少数人最终能精通语言,成为执牛耳者,他们是金字塔的最顶层.虽然万事开头难,但好的开始是成功的一半,今天这篇文章就来谈谈如 ...
- javascript痛点之三闭包
先来看看第一节的例子 'use strict'; function num(){ //用var声明一个变量num1 var num1 = 15; } alert(num1);//num1 is not ...