UE4网络中UObject创建和销毁

本文中我们专注ContentBlockPayloadHeader和DeleteObject信息.

  1. UObject DS怎么序列化的? (ContentBlockHeader)
  2. 客户端怎么创建的? (ContentBlockHeader)
  3. 既不序列化也不创建, 仅仅是持有指针, 怎么映射的? (GUID)
  4. DS是怎么判断需要根据GUID创建, 而不是映射呢? (ContentBlockHeader)

简述

首先我们看一下ReplicationActor的简要流程, 从下图可以看出, 其一个Actor进行Replication的时候分成三部分: Replicate自身属性+Replicate ActorComponent属性+Replicate SubObject属性. 但是最终都会调用核心函数FObjectReplicator::ReplicateProperties对属性进行处理. FObjectReplicator::ReplicateProperties流程也是四部曲:UpdateChangeList(更新属性:这帧和上一帧对比)+UpdateChangedHistory(清理合并历史变化)+更新CustomDeltaProperty(FastArray类型)+合并UnreliableFunction.

ContentBlockHeader:但是我们今天要讲的不是这些, 而是ContentBlockHeader. 它又是何方神圣呢? 先思考一个问题:如果标志当前修改的属性归属于哪个UObject? 只有知道当前要修改哪个UObject, 然后根据属性信息找到对应的属性, 即可做出修改处理. ContentBlockHeader就是做UObject定位的.它能唯一标识当前针对哪个UObject进行修改.

DS序列化

每个需要ReplicationUObject都会有一个对应的FObjectReplicator, 在UObject的属性序列化完成之后, 在添加ContentBlockHeader, 将这些属性做归属, 即属于哪个UObject的修改.

ContentBlockHeader信息序列化

这里还要特殊说明一下, IsNameStableForNetworking表明客户端是否可以进行创建, 如果为DefaultSubComponent或者其他的默认就会创建的, 该属性为1, 表明不允许客户端创建, 只能查询绑定.

填充流程

具体代码解析:

这里还需要注意一点是, 当第一次创建UObject对应的ObjectReplicator时, 还将Bunch设置为Reliable. 即该Channel第一次同步(Channel可能会反复创建, 没重新创建Channel会重新生成ObjectReplicator)该属性则Bunch特意设置为ReliableBunch.

Delete信息序列化

这个很简单, 就是遍历ReplicationMap中所有成员, 针对NotValid的成员就视作删除, 填充Delete信息.

客户端反序列化

客户端首先解析ContentBlockHeader, 然后才能确定当前修改的是哪个UObject.

创建

如果SubObj为空, 则直接创建.

bStablyNamed类型只能Find, 不能Create.

删除

在解析ContentBlockHeader时候, 发现如果ClassGUID为0, 就视作删除消息, 直接删除对应UObject.

总结

  1. UObject的创建和删除时通过ContentBlockHeader表示的.
  2. ReplicationObjectOwner需要为其创建, Propertie的网络同步, 以及删除负责, 通过ContentBlockHeader实现. 其他对象则只有其GUID的使用权.
  3. 自定义UObject进行Replicate请参考文章:自定义UObject进行Replicate, 这里不再赘述.
  4. 如果仅仅使用GUID, 没有ContentBlockHeader, 则只负责映射, 不进行创建, Propertie的网络同步, 以及删除.
  5. 网络时序引起的逻辑问题, 要用逻辑去矫正. 比如使用A的Replication先到了, 但是还没创建, 则需要逻辑去保证其正确性.
  6. 其实Delete消息是ContentBlockHeader的特例而已.
  7. Channel第一次同步某个UObject的时候(创建ObjectReplicator), 会将Bunch设置为Reliable.