自定义UObject进行Replicate
UE本身有一套自创的网络框架, 在这个框架里UObject类型默认是无法进行属性同步的. 如果想要UObject进行属性同步就必须进行一系列重写.
UE本身有一套自创的网络框架, 在这个框架里UObject类型默认是无法进行属性同步的. 如果想要UObject进行属性同步就必须进行一系列重写.
开启网络相关日志:
1 | log LogNetTraffic log |
关闭网络相关日志:
1 | log LogNetTraffic off |
开启DS端络相关日志:
1 | ServerExec log LogNetTraffic log |
UE中加载机制是, 加载会有一个队列, 一个同步加载会flush掉前面所有的异步加载, 进而造成卡顿. 例如: 当前存在异步加载A和B, 此时我调用同步加载C, 会立即将A和B flush掉, 然后执行C.
UE NetAsyncLoad大致流程:
在TickDispatch(收包)阶段,
针对所有ExportNetGUID(这里就指其所对应的UObject, 下同)进行异步加载,
并将其填入PendingGuidResolves
中. 在接收Bunch中,
如果需要等待GUID加载或者QueuedBunch还没处理完,
就将该Bunch添加到QueueBunch中.
在TickFlush(发包)阶段, 解析GUID,
如果PendingGuidResolves
为空, 并且其他条件也满足了,
就会处理QueueBunches.
可以看到上述流程中, 如果PendingGUID都已经被解析了, 那么走的流程和正规流程没什么区别. 如果存在没有被解析的PendingGUID, 则会将Bunch放入QueuedBunches中.
FRepChangedPropertyTracker
存储着一帧对应Object Parent Properties
是否Dirty
.
每个Object
只有一份FRepChangedPropertyTracker
,
所有Connection
共享,
它标志着该Object内Parent层级的属性是否Dirty,
并存储在UNetDriver.RepChangedPropertyTrackerMap
中(关键函数UNetDriver::FindOrCreateRepChangedPropertyTracker
).
并且FRepChangedPropertyTracker.Parents
初始化时候默认为1,
即Dirty. 而且不会自动清理, 即如果使用就要自己维护.
根据FVector三个分量的最大值, 压缩Vector, 节省带宽. 这里还要注意一点, 当数值比较大时, 可能压缩后比压缩前占用的bit数量还要大, 即更占用带宽.
1 | /** Amount of time to wait for a new net connection to be established before destroying the connection */ |
仿照CVarRepGraphConditionalBreakpointActorName
,
添加自己需要条件段断点的地方.
在进行属性同步时, 每当一个属性发生变化都要发给关心该属性的所有Connection, 如果这些Connection共享一份, 那就可以节省很多内存, 序列化等时间.
一般与WithNetSerializer
组合使用.
WithIdenticalViaEquality
是什么在属性同步时候, 如果想自定义比较函数应该怎么处理呢?
WithIdenticalViaEquality
就是表明该结构体使用Operator ==
进行比较.
注意它和WithIdentical
互斥.
ReplicateActor
分成三步:
SerializeNewActor
+序列化属性
+序列化删除的Objs
.
其中序列化属性中的属性又分成三类:
Actor自身属性
+ActorComponent属性
+SubObject属性
.
每类属性的序列化都会调用同一个函数:
FObjectReplicator::ReplicateProperties
.
本文中我们专注ContentBlockPayloadHeader和DeleteObject信息.
当指针类型进行OnRep时候, 可能会触发两次. 触发条件为