Unreal属性同步机制
因为工作需要,需要整理一下属性复制流程
//复制准备
void AActor::PreReplication(IRepChangedPropertyTracker & ChangedPropertyTracker)
{
// Attachment replication gets filled in by GatherCurrentMovement(), but in the case of a detached root we need to trigger remote detachment.
AttachmentReplication.AttachParent = nullptr;
AttachmentReplication.AttachComponent = nullptr;
//打包移动相关的属性到ReplicatedMovement结构体中,准备复制
GatherCurrentMovement();
DOREPLIFETIME_ACTIVE_OVERRIDE(AActor, ReplicatedMovement, IsReplicatingMovement());
// Don't need to replicate AttachmentReplication if the root component replicates, because it already handles it.
DOREPLIFETIME_ACTIVE_OVERRIDE(AActor, AttachmentReplication, RootComponent && !RootComponent->GetIsReplicated());
PRAGMA_DISABLE_DEPRECATION_WARNINGS
UBlueprintGeneratedClass* BPClass = Cast<UBlueprintGeneratedClass>(GetClass());
if (BPClass != nullptr)
{
BPClass->InstancePreReplication(this, ChangedPropertyTracker);
}
PRAGMA_ENABLE_DEPRECATION_WARNINGS
}
打包移动相关属性,包括子对象
//移动属性打包,包括子对象属性打包
void AActor::GatherCurrentMovement()
{
// 需要复制移动属性 || 包含子对象
if (IsReplicatingMovement() || (RootComponent && RootComponent->GetAttachParent()))
{
bool bWasAttachmentModified = false;
bool bWasRepMovementModified = false;
//暂存附加的旧对象
AActor* OldAttachParent = AttachmentReplication.AttachParent;
USceneComponent* OldAttachComponent = AttachmentReplication.AttachComponent;
//附加复制对象重置为空
AttachmentReplication.AttachParent = nullptr;
AttachmentReplication.AttachComponent = nullptr;
UPrimitiveComponent* RootPrimComp = Cast<UPrimitiveComponent>(GetRootComponent());
//需要物理模拟,打包物理属性进行同步
if (RootPrimComp && RootPrimComp->IsSimulatingPhysics())
{
FRigidBodyState RBState;
RootPrimComp->GetRigidBodyState(RBState);
ReplicatedMovement.FillFrom(RBState, this);
// Technically, the values might have stayed the same, but we'll just assume they've changed.
bWasRepMovementModified = true;
}
//如果存在根组件
else if (RootComponent != nullptr)
{
// If we are attached, don't replicate absolute position, use AttachmentReplication instead.
if (RootComponent->GetAttachParent() != nullptr)
{
// Networking for attachments assumes the RootComponent of the AttachParent actor.
// If that's not the case, we can't update this, as the client wouldn't be able to resolve the Component and would detach as a result.
AttachmentReplication.AttachParent = RootComponent->GetAttachParent()->GetAttachmentRootActor();
if (AttachmentReplication.AttachParent != nullptr)
{
//复制移动修正属性到AttachmentReplication
AttachmentReplication.LocationOffset = RootComponent->GetRelativeLocation();
AttachmentReplication.RotationOffset = RootComponent->GetRelativeRotation();
AttachmentReplication.RelativeScale3D = RootComponent->GetRelativeScale3D();
AttachmentReplication.AttachComponent = RootComponent->GetAttachParent();
AttachmentReplication.AttachSocket = RootComponent->GetAttachSocketName();
// Technically, the values might have stayed the same, but we'll just assume they've changed.
bWasAttachmentModified = true;
}
}
//如果自身就是根组件
else
{
ReplicatedMovement.Location = FRepMovement::RebaseOntoZeroOrigin(RootComponent->GetComponentLocation(), this);
ReplicatedMovement.Rotation = RootComponent->GetComponentRotation();
ReplicatedMovement.LinearVelocity = GetVelocity();
ReplicatedMovement.AngularVelocity = FVector::ZeroVector;
// Technically, the values might have stayed the same, but we'll just assume they've changed.
bWasRepMovementModified = true;
}
bWasRepMovementModified = (bWasRepMovementModified || ReplicatedMovement.bRepPhysics);
ReplicatedMovement.bRepPhysics = false;
}
//如果Movement数据有修改,make dirty
if (bWasRepMovementModified)
{
MARK_PROPERTY_DIRTY_FROM_NAME(AActor, ReplicatedMovement, this);
}
//如果关联对象有修改,make dirty
if (bWasAttachmentModified ||
OldAttachParent != AttachmentReplication.AttachParent ||
OldAttachComponent != AttachmentReplication.AttachComponent)
{
MARK_PROPERTY_DIRTY_FROM_NAME(AActor, AttachmentReplication, this);
}
}
}
认真写好每一行代码