GUID延迟绑定

延迟绑定

UE对UObject指针的映射是通过GUID进行的, 例如当客户端ABasePlayerController.TestReplicationComp2需要根据DS传来的新数据进行赋值, 这个值就是GUID其代表一个对象.

首先需要了解到, UE序列化是有顺序的, ActorProperties->ActorComponentProperties->SelfReplicatedObjProperties.

当属性的赋值在GUID对象创建之前, 因为指针对象还没有创建, 那么指针就不可能指向正确的地址. 这种情况该怎么处理呢? 例如当客户端ABasePlayerController.TestReplicationComp2需要反序列化的时候, 发现该GUID表示的对象还不存在, 这时候怎么办?

U根据UE处理属性同步的顺序(ActorProperties->ActorComponentProperties->SelfReplicatedObjProperties), 先反序列化属性变量, 发现没有找到GUID对应的UObj, 将其放入临时存储变量UPackageMap.TrackedUnmappedNetGuids中(详见特殊说明1).

并将结果添加到FReceivingRepState.GuidReferencesMap中.

并且如果检测到有Unmapped数据, 还要将其添加到UNetDriver.UnmappedReplicators中.

在每帧末尾会处理UNetDriver.UnmappedReplicators中未处理的UnmappedGUID.

通过以上逻辑, 就可以将ABasePlayerController.TestReplicationComp2指向对应的Obj了.

思考:

如果在反序列化属性时, GUID没有找到, 那么该属性会更改吗?

在序列化TestReplicationComp2时, 可以看出, 当没有解析出GUID对应的Object时, Obj会设置成nullptr, 然后将nullptr设置到TestReplicationComp2中.

image-20230628205408507

但是这种情况只是短暂存在的, 即在UNetDriver.TickFlush结尾就已经将TestReplicationComp2设置成正确的值了.

进一步思考, 在属性同步的时候, 是否会发生将TestReplicationComp2设置成nullptr, 过了几帧才将TestReplicationComp2设置成正确的值呢? 这种情况发生的条件为GUID同步过来了, 但是其真正的对象在后续才创建. 针对Owner为Actor本身的Component不可能出现, 当一个属性发生变化, 如果查找到该GUID对象的Obj, 则直接设置, 否则后续一定会紧跟着GUID对应Obj的创建. 但是针对一个指针, 指向别的Actor/UObject, 是可能出现: GUID有了, 但是Actor/UObject还没

特殊说明

UnmappedNetGuids和MappedDynamicNetGuids临时存储

UPackageMap.TrackedUnmappedNetGuids和UPackageMap.TrackedMappedDynamicNetGuids都是临时存储数据用的, 用完即清理.

UnmappedNetGuids用途

针对UnmappedGUID主要是用于延迟绑定. 绑定后, 如果GUID为Dynamic, 则将其放入MappedDynamic

每帧处理UnmappedGUID.

MappedDynamic用途

收集UnmappedGUID和MappedGUID, 填充UNetDriver.GuidToReplicatorMap数据, 供后续使用.