ET篇:master消息机制介绍(一般消息的流转)
终于到了核心部分之一了——消息机制
既然讲到消息,我们要到消息的源头——客户端
来到Unity.Hotfix的Init文件,并定位到这一句
Game.EventSystem.Run(EventIdType.InitSceneStart);
他会执行这里的Run代码(不知道为何的去复习ETBook的EventSystem哦)
进入UILoginFactory,他是登录UI的工厂类,在这个工厂将完成一系列的操作
//获取资源组件,用以加载资源
ResourcesComponent resourcesComponent = ETModel.Game.Scene.GetComponent<ResourcesComponent>();
//加载UI的AB包
resourcesComponent.LoadBundle(UIType.UILogin.StringToAB());
//获取到登录UI
GameObject bundleGameObject = (GameObject)resourcesComponent.GetAsset(UIType.UILogin.StringToAB(), UIType.UILogin);
//实例化登录UI
GameObject gameObject = UnityEngine.Object.Instantiate(bundleGameObject);
//在组件工厂创建UI(主要是为了能给游戏物体添加上组件做准备)
UI ui = ComponentFactory.Create<UI, string, GameObject>(UIType.UILogin, gameObject, false);
//为UI添加登录UI组件
ui.AddComponent<UILoginComponent>();
然后我们知道添加一个组件会执行其的Awake函数(如果存在并写明了继承自AwakeSystem的类),我们看到,他在Awake里面从其挂载的ReferenceCollector取得自身子物体的引用,并且为Button添加了点击事件
public void Awake()
{ReferenceCollector rc = this.GetParent<UI().GameObject.GetComponent<ReferenceCollector>();loginBtn = rc.Get<GameObject>("LoginBtn");loginBtn.GetComponent<Button>().onClick.Add(OnLogin);this.account = rc.Get<GameObject>("Account");
}public void OnLogin()
{LoginHelper.OnLoginAsync(this.account.GetComponent<InputField>().text).Coroutine();
}
那么我们去看OnLoginAsync函数 ,知道我为什么在最后空两行吗?(观众:装起来了???)
是因为这里用的await 和 Session.Call方法,await是阻塞方法,在返回结果之前不会继续往下走,而Call是要求有反馈消息的,综上只有在收到消息或者遇到异常才会有可能(异常的话程序将停止运行)执行到R2C_Login reCLogin这里,然后才会走最后一行
// 创建一个ETModel层的Session
ETModel.Session session = ETModel.Game.Scene.GetComponent<NetOuterComponent>().Create(GlobalConfigComponent.Instance.GlobalProto.Address);
// 创建一个ETHotfix层的Session, ETHotfix的Session会通过ETModel层的Session发送消息
Session realmSession = ComponentFactory.Create<Session, ETModel.Session>(session);
//发送登录请求,账号,密码均为传来的参数(理应这样,但这是例子,就无所谓了)
R2C_Login r2CLogin = (R2C_Login) await realmSession.Call(new C2R_Login() { Account = account, Password = "111111" });//释放realmSession
realmSession.Dispose();
注意 第二句的Awake注册了消息回调函数,并且这里的Session是ETHotfix的,与ETModel下的Session有区别
public override void Awake(Session self, ETModel.Session session)
{self.session = session;SessionCallbackComponent sessionComponent = self.session.AddComponent<SessionCallbackComponent>();sessionComponent.MessageCallback = (s, opcode, memoryStream) => { self.Run(s, opcode, memoryStream); };sessionComponent.DisposeCallback = s => { self.Dispose(); };
}
好,既然消息发走了,我们就去看服务端了
我们直接从NetworkComponent看起吧(事实上客户端和服务端用的是同一个NetworkComponent,所以这里的NetworkComponent组件看完就不需要重复看客户端的了)
// 外网消息组件
Game.Scene.AddComponent<NetOuterComponent, string>(outerConfig.Address);||
\|/
K component = ComponentFactory.CreateWithParent<K, P1>(this, p1, this.IsFromPool);||
\|/
Game.EventSystem.Awake(component, a);||
\|/
[ObjectSystem]
public class NetOuterComponentAwake1System : AwakeSystem<NetOuterComponent, string>
{public override void Awake(NetOuterComponent self, string address){}
}||
\|/
public void Awake(NetworkProtocol protocol, string address, int packetSize = Packet.PacketSizeLength2)
{
}
因为默认是TCP,所以绑定OnAccept(当收到消息,他会被调用)
public void OnAccept(AChannel channel)||
\|/
//ETModel.Session.cs
public void Awake(AChannel aChannel)||
\|/
注册收到消息回调函数
//ETModel.Session.cs
public void OnRead(MemoryStream memoryStream)||
\|/
//TChannel.cs
public override void Start()||
\|/
开始接收消息
//TChannel.cs
private void StartRecv()||
\|/
接收消息完毕,解析好收到的信息,通过消息回调函数处理消息,
如果是热更层的消息,就调用ETHotfix.Session里注册的回调函数处理,
否则就用ETModel.Session里的函数处理,
(其实两者也是大同小异,大家可以自行查看各个Session的Run函数)
这里面又涉及到消息分发组件MessageDispatcherComponent以及requestCallback的细节,
大家可以自行查看
最后发送消息||
\|/
//TChannel.cs
public void StartSend()
更多细节我会在之后介绍,我们这里的Handler是C2R_LoginHandler.cs
//这里是进行数据库验证,作为例子,这里去掉了验证
//if (message.Account != "abcdef" || message.Password != "111111")
//{
// response.Error = ErrorCode.ERR_AccountOrPasswordError;
// reply(response);
// return;
//}// 随机分配一个Gate
StartConfig config = Game.Scene.GetComponent<RealmGateAddressComponent>().GetAddress();
//Log.Debug($"gate address: {MongoHelper.ToJson(config)}");//读取内部服务器地址
IPEndPoint innerAddress = config.GetComponent<InnerConfig>().IPEndPoint;//从地址缓存中取Session,如果没有则创建一个新的Session,并且保存到地址缓存中
Session gateSession = Game.Scene.GetComponent<NetInnerComponent>().Get(innerAddress);// 向gate服务器请求一个key,客户端可以拿着这个key连接gate
G2R_GetLoginKey g2RGetLoginKey = (G2R_GetLoginKey)await gateSession.Call(new R2G_GetLoginKey() {Account = message.Account});//上述过程已完成,将执行这句,获取外部服务器地址
string outerAddress = config.GetComponent<OuterConfig>().Address2;//设置返回的信息
response.Address = outerAddress;
response.Key = g2RGetLoginKey.Key;
//回复客户端的登录请求
reply(response);
好了,服务端的消息发过来了,我们客户端要响应吧,再回到客户端,这时候r2CLogin已经被赋好值了,可以进行下面的操作了。
ET篇:master消息机制介绍(一般消息的流转)相关推荐
- Unity中简单粗暴的消息机制(可限制消息调用次数)
上代码 /********************************************************文件: EasyMsg.cs作者: 阿飞日期: 2022年02月15日_09: ...
- Handler消息机制介绍,流程梳理
文章目录 前言 基本使用 发送和处理Runnable 发送和处理Message 流程梳理 获取消息 发送消息 消息入队 消息出队 理解 源码分析 前言 Handler 是Android 的消息处理机制 ...
- odoo14 mail.thread邮件消息机制(发送消息、字段变化跟踪记录)mail.activity.mixin安排活动
odoo内部的消息机制是十分便捷的,可以使用odoo 系统消息进行沟通,也可以通过odoo代发邮件进行沟通. 通过点击系统右上角的用户名,在弹出的下拉框中选择 '首选项' ,我们可以设置email选项 ...
- android handler的机制和原理_一文搞懂handler:彻底明白Android消息机制的原理及源码
提起Android消息机制,想必都不陌生.其中包含三个部分:Handler,MessageQueue以及Looper,三者共同协作,完成消息机制的运行.本篇文章将由浅入深解析Android消息机制的运 ...
- windows消息机制详解-3
1. 引言 Windows 在操作系统平台占有绝对统治地位,基于Windows 的编程和开发越来越广泛. Dos 是过程驱动的,而Windows 是事件驱动的[6],这种差别的存在使得很多Dos 程序 ...
- Windows 消息机制浅析
Windows 消息机制浅析 1. Windows 的历史 中国人喜欢以史为鉴,而事实也确实是,如果你能知道一件事情的来龙去脉,往往可以更容易地理解事物为什么会表现为当前这样的现状.所以, ...
- eCos消息机制学习
消息机制学习 消息机制介绍 消息机制也是学习eCos平台框架必不可少的一方面,主要负责CGI与各个模块以及各个模块之间的通讯机制,效果与UGW平台相似,但消息机制本身实现方式不同,下图是其整体的流程图 ...
- win32mfc————win32消息机制
文章目录 文章目录 文章目录 前言 一.`消息机制`是什么 二.Windows消息机制 1.产生消息 2.消息传递 3.消息处理 三.基本消息 1.窗口创建消息 2.窗口销毁 3.窗口激活 重要消息 ...
- 【安卓学习笔记】Android Handler 消息机制探究
一.概述 1.android消息机制的含义: Android消息机制,其实指的就是 Handler 的运行机制,而 Handler 要正常运作,又需要底层的 MessageQueue , Looper ...
最新文章
- Mybatis实现分库分表
- MATLAB-循环类型相关(for while break continue)
- 机器人学习--Turtelbot3学习-- Burger与waffle等版本的切换
- Ctr点击率预估理论基础及项目实战
- 安装python的pip模块
- [转]:xmake工程描述编写之选择性编译
- gpu跑普通python程序_普通电脑PC怎样跑TensorFlow的GPU模式
- WebForm与MVC模式优缺点
- vs2017通过ODAC连接oracle11g
- excel如何快速查询银行卡号实名认证?
- php生成appid,请求认证密钥-AppID
- 程序员面试被问,有没有别家的offer?这个问题怎么回答?
- CodeForces 1437F Emotional Fishermen(计数dp)
- Ubuntu12.10 使用DNW传数据 进行ARM开发板烧写
- 以太网采集欧姆龙PLC DM数据并存入ACCESS 使用C#编写上位机程序
- lamp +discuz+wordpress+phpmyadmin实例安装详解
- 文库自由复制(纯文本)
- Java面试:字节跳动+京东+360+网易面试题整理
- Oracle实现动态行转列
- 火山安卓卡片布局器基本使用方式