前言
UE同步是一块比较复杂而庞大的模块,里面设计到了很多设计思想,技巧,技术。我这里主要是从同步的流程分析,以同步的机制为讲解核心,给大家描述里面是怎么同步的,会大量涉及UE同步模块的底层代码,稍微涉及一点计算机网络底层(Socket相关)相关的知识。
PS:如果只是想知道怎么使用同步,不建议阅读这篇文章,不过可以参考我另外一篇博客 UE4网络同步(一)——理解同步规则
另外,博主参考的源码版本比较旧,有些细节略有差异,大家可以作为参考。有时间我会对此进行更新
目录
一.基本概念
二.通信的基本流程
三.连接的建立
-
- 服务器网络模块初始化流程
-
- 客户端网络模块初始化流程
-
- 服务器与客户端建立连接流程
四.Actor的同步细节
五.属性同步细节
-
- 属性同步概述
-
- 重要数据的初始化流程
-
- 发送同步数据流程分析
-
- 属性回调函数执行
-
- 关于动态数组与结构体的同步
六.RPC执行细节
七.其他网络特性
-
- Reliable与可靠数据传输
一. 基本概念
UE网络是一个相当复杂的模块,这篇文档主要是针对Actor同步,属性同步,RPC等大致的阐述一些流程以及关键的一些类。这里我尽可能将我的理解写下来。
在UE里面有一些和同步相关的概念与类,这里逐个列举一下并做解释:
底层通信:
- Bunch
一个Bunch里面主要记录了Channel信息,NGUID。同时包含其他的附属信息如是否是完整的Bunch,是否是可靠的等等,可以简单理解为一个数据包,该数据包的数据可能不完整,继承自FNetBitWriter
InBunch:从Channel接收的数据流串
OutBunch:从Channel产生的数据流串 - FBitWriter
字节流书写器,可以临时写入比特数据用于传输,存储等,继承自FArchive - FSocket
所有平台Socket的基类。
FSocketBSD:使用winSocket的Socket封装 - Packet
从Socket读出来/输出的数据 - UPackageMap
生成与维护Object与NGUID的映射,负责Object的序列化。每一个Connection对应一个UPackageMap
(Packet与Bunch的区别:Packet里面可能不包含Bunch信息)
基本网络通信:
- NetDriver
网络驱动,实际上我们创建使用的是他的子类IPNetDriver,里面封装了基本的同步Actor的操作,初始化客户端与服务器的连接,建立属性记录表,处理RPC函数,创建Socket,构建并管理当前Connection信息,接收数据包等等基本操作。NetDriver与World一一对应,在一个游戏世界里面只存在一个NetDriver。UE里面默认的都是基于UDPSocket进行通信的。 - Connection
表示一个网络连接。服务器上,一个客户端到一个服务器的一个连接叫一个ClientConnection。在客户端上,一个服务器到一个客户端的连接叫一个ServerConnection。 - LocalPlayer
本地玩家,一个客户端的窗口ViewportClient对应一个LocalPlayer,Localplayer在各个地图切换时不会改变。 - Channel
数据通道,每一个通道只负责交换某一个特定类型特定实例的数据信息。ControlChannel:客户端服务器之间发送控制信息,主要是发送接收连接与断开的相关消息。在一个Connection中只会在初始化连接的时候创建一个该通道实例。
VoiceChannel:用于发送接收语音消息。在一个Connection中只会在初始化连接的时候创建一个该通道实例。
ActorChannel:处理Actor本身相关信息的同步,包括自身的同步以及子组件,属性的同步,RPC调用等。每个Connection连接里的每个同步的Actor都对应着一个ActorChannel实例。
常见的只有这3种:枚举里面还有FileChannel等类型,不过没有使用。 - PlayerController
玩家控制器,对应一个LocalPlayer,代替本地玩家控制游戏角色。同时对应一个Connection,记录了当前的连接信息,这和RPC以及条件属性复制都是密切相关的。另外,PlayerController记录他本身的ViewTarget(就是他控制额Character),通过与ViewTarget的距离(太远的Actor不会同步)来进行其他Actor的同步处理。 - World
游戏世界,任何游戏逻辑都是在World里面处理的,Actor的同步也受World控制,World知道哪些Actor应该同步,保存了网络通信的基础设施NetDriver。 - Actor
在世界存在的对象,没有坐标。UE4大部分的同步功能都是围绕Actor来实现的。 - Dormant
休眠,对于休眠的Actor不会进行网络同步
属性同步相关:
- FObjectReplicator
属性同步的执行器,每个Actorchannel对应一个FObjectReplicator,每一个FObjectReplicator对应一个对象实例。设置ActorChannel通道的时候会创建出来。 - FRepState
针对每个连接同步的历史数据,记录同步前用于比较的Object对象信息,存在于FObjectReplicator里面。 - FRepLayOut
同步的属性布局表,记录所有当前类需要同步的属性,每个类或者RPC函数有一个。 - FRepChangedPropertyTracker
属性变化轨迹记录,一般在同步Actor前创建,Actor销毁的时候删掉。
二. 通信的基本流程
如果我们接触过网络通信,应该了解只要知道对方的IP地址以及端口号,服务器A上进程M_1_Server可以通过套接字向客户端B上的进程M_1_Client发送消息,大致的效果如下:
- 图2-1 远程进程通信图
而对于UE4进程内部服务器Server与客户端Client1的通信,与上面的模型基本相似: