任务43:重要知识点(长期更新中...)

更新中...

#################### 学习方法 ####################

根据自己的思维习惯选择不同的学习方式。建议先优先建立对服务端通信往来的模型,先不要过于关注每句代码全部想一开始就明白。

知道如何通信,能把注册,登录,进房间,发牌这些如何在map,gate,reale之间建立通信往来,先跟着主线做出来,能最直观直接的体会到,这个更关键。

比如说:

ET的事件系统,不明白为什么这样写,但是课程里反复告诉你怎么用了。

FairyGUI,ET UI组件,不明白为什么这样写,但能看明白怎么用了。另个你得会不用FairyGUI应该也能做出来,要理解核心通信。

代码很多使用了特性,泛型,接口,抽象类与方法,扩展方法。跟着写跟着用,过段时间自己全会用了,越来越加深理解。

记住:整个课程的学习重点关注的是服务端通信,请求,消息,响应请求的Handler,通用的服务端功能实现。

#################### 学习方法 ####################

开发运行环境:

前端需要.net framework,后端需要.netcore 

详细的环境安装 https://www.taikr.com/course/1053/task/30933/show

 

理解项目管理:

前端可以创建程序集.asmdef来管理项目代码,别都直接放在Assets下面,用Unity自动生成的Assembly-CSharp管理项目代码。https://www.taikr.com/course/1053/task/30931/show

代码都需要在一个项目中编译后才能被执行。一个项目会生成一个dll,你的C#项目都是.net运行时中运行这些dll来执行的。

Unity会帮你生成解决方案.sln,和c#项目.csproj。

服务端自己创建.sln,和c#项目.csproj,项目可以引用别的项目,也就是不同dll的引用。

 

ETCore的使用

Unity项目中,只需要要包含ET.Core项目(核心,与服务端代码一样),就能使用ET来进行网络请求与通信,Model项目中包含了少量现成提供可复用的组件,我们自己游戏的代码可以放在Model中,也可以另外创建一个项目引用ET.Core与Model即可。

需要引用ThirdParty项目,这里有mongo,protobuf,fairgui这些第三方sdk。

服务端项目中,系统逻辑与Handler都在Hotfix项目中编写,你自己项目的服务端代码主要在这里。后端ET.Core项目中可以加你自己游戏的实体,组件,系统类。

Handler是请求的响应,与功能逻辑实现的地方。System是组件的扩展方法,来帮助把需要的组件加入到系统的生命周期里(start,load,awake,update等)。

消息指令与消息体在ET.Core项目中 \ET.Core\Module\Message\目录下。

 

Session使用

用地址创建session 

远程地址:127.0.0.1:10002

Session sessionRealm = Game.Scene.GetComponent<NetOuterComponent>().Create("127.0.0.1:10002");

Session sessionRealm = Game.Scene.GetComponent<NetOuterComponent>().Create(GlobalConfigComponent.Instance.GlobalProto.Address);

GlobalConfigComponent.Instance.GlobalProto.Address就是配置文件中获取到像上面的远程地址。

用IPEndPoint创建session 

public IPEndPoint(long address, int port);

IPEndPoint realmIPEndPoint = new IPEndPoint(Int64.Parse("127.0.0.1"),10002);
Session realmSession = Game.Scene.GetComponent<NetOuterComponent>().Create(realmIPEndPoint);

不需要返回发送消息 session.Send

Send方法的参数是一个消息体

realmSession.Send(new A0004_PlayerOnline_G2R() { UserID = user.UserID, GateAppID = config.StartConfig.AppId });

发送请求获得返回 session.Call

Call方法的参数是一个请求消息体,返回一个响应消息体

A1002_SetUserInfo_G2C SetUserInfo_Ack = (A1002_SetUserInfo_G2C)await SessionComponent.Instance.Session.Call(SetUserInfo_Req);

消息指令、消息体

消息指令是前后端,不同服务端之间的“接头暗号”,收到消息后,通过指令就知是什么消息体类型了,或者找出对应的Handler来执行。

消息体,是把消息内容的不同字段构建一个消息体类型的实例,用实例属性来使用消息数据。

ET是先用数据构建消息体实例,把消息对象序列化为json或profobuf数据进行传送,收到消息再反序列化为消息对象在程序中使用。

消息与handler命名参考举例:消息名需要先知道他是什么功能,再怎么往来。消息处理handler需要先知道从哪来,再是什么功能。方便开发时保持思路清晰。

[功能表达]+[往来] :GetUserInfo_C2G,GetUserInfo_G2C

当然如果你更习惯统一:C2G_TestMessage

如果是IActorMessage :Actor_MatchSucess_M2G

收到消息后处理handler :M2G_MatchSucess_Handler

认证服务Realm:R ,网关服务Gate:G,地图服务Map:M,客户端Client:C

 

消息指令与消息体定义

message C2G_TestMessage // IRequest

请求名后面带上 // IRequest 这样生成的消息体就会继承IRequest

message G2C_TestMessage // IResponse

返回名后面带上 //IResponse 这样生成的消息体就会继承IResponse

//测试向服务器返回消息
message G2C_TestMessage // IResponse
{
    int32 RpcId = 90;
    int32 Error = 91;
    string Message = 92;
}

HotfixMessage.cs,HotfixOpcode.cs,InnerMessage.cs,InnerOpcode.cs,OuterMessage.cs,OuterOpcode.cs

在我们的课程里,统一把他们都放在这个目录下:

\Assets\ET.Core\Module\Message\

InnerMessage:不同服务之间通信消息

OuterMessage:前后端通信消息

HotfixMessage:前后端通信消息,无热更的ETCore来说与OuterMessage没区别

 

自动生成消息指令与消息体类

Proto的unity编辑器扩展工具,放在Assets>Editor目录中 Proto2CsEditor.zip

proto生成工具 Proto.zip

https://www.taikr.com/course/1053/task/30953/show

更新 .proto 文件后,到unity中找到菜单点Tools>Ptoto2CS工具,确认下重新生成的消息体类与指令脚本,复制一份放到服务端。

前端消息类与指令脚本在 \Assets\ET.Core\Module\Message\

后端消息类与指令脚本复制前端生成的文件到 \Server\ET.Core\Module\Message\

 

断线重连要点:

  1. 处理好与用户主动下线的关系,别主动下线下线不了
  2. 客户端发现断线,请求重连
  3. 服务端发现断线,保留用户数据,游戏地图中数据15分钟
  4. 服务端收到重连请求,把重连数据发给客户端

状态同步,还要理清楚哪些是触发式保存的数据,哪些是每分钟保存的数据,还不能冲突了,漏了。

比如说:

角色走来走去,背包装备移这个格子那个格子,技能拖到不同的工具条格子,装备换来换去,许多这类玩家的“无聊”操作并不会触发保存数据库,是每分钟统一保存角色数据的。

比如新获得了装备,经验,升级,货币增加,接,完成任务这些有意义的东西会更新角色数据内存和更新数据库。

 

实体间Actor通信:

理解为什么要用actor通信:

Entity.Id是实体的身份证号,instanceID是居住证号,实体instanceID是会换的,比如到了别的地图。actor系统会保存你的身份证和你在哪个地图的居住证。如果用居住证能找到你,就用instanceId把消息发给你了,如果找不到,就会用身份证找到你新的居住证,再把消息发给你。

总结一下几种给实体添加消息组件:

复制代码
//网关上的user实体是不是变动的,加消息组件,没有参数也没有AddLoaction()
user.AddComponent<MailBoxComponent>();

//session实体是客户端与网关的连接session,向此实体发消息,会转发到客户端,加消息组件带MailboxType.GateSession参数
session.AddComponent<MailBoxComponent, string>(MailboxType.GateSession);

//room,gamer实体会迁移地图,加消息组件有AddLoaction()
room.AddComponent<MailBoxComponent>().AddLocation();
newgamer.AddComponent<MailBoxComponent>().AddLocation();
复制代码

命令行运行FileServer.dll

打开命令行工具到达FileServer目录

输入命令:dotnet FileServer.dll

复制代码
C:\Users\Rman-xvr>e:
E:\>cd E:\ETCoreLandlords\ET0X_Landlords_Client\FileServer

E:\ETCoreLandlords\ET0X_Landlords_Client\FileServer>dotnet FileServer.dll
E:\ETCoreLandlords\ET0X_Landlords_Client\Release\
Hosting environment: Production
Content root path: E:\ETCoreLandlords\ET0X_Landlords_Client\FileServer
Now listening on: http://[::]:8088
Now listening on: http://[::]:8080
Application started. Press Ctrl+C to shut down.
复制代码

Protobuf : repeated类型

 

使用Game.Scene

Game.Scene 是ETCore框架的全局实体对象,如果你有某种组件,需要在全局范围调用他的属性和方法,那就应该在需要的时候把此组件添加给Game.Scene。

Game.Scene.AddComponent<XXX组件>();

Game.Scene.GetComponent<XXX组件>();

 

ET.Core事件

 

Handler特性

[MessageHandler(AppType.Gate)] 

 

UIFactory特性

[UIFactory(FUIType.SetUserInfo)]

 

创建实体或组件

 

向组件扩展方法传参

 

posted @   Domefy  阅读(30)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示