3.0 KiB
Raw Blame History

前言

继承关系BP_XXX_Base -> BP_Idol_Base -> TsIdolActor -> AVCharacter -> ACharacter 。 主要逻辑位于TsIdolActor中文件路径为Script/LiveDirector/Character/TsIdolActor.ts

AVCharacter

主要实现了virtual void OnRep_AttachmentReplication() override;声明了若干BlueprintNativeEvent

  • bool CanSyncRelativeTransform();
  • void BeforeAttachToNewParent();
  • void AfterAttachToNewParent();

OnRep_AttachmentReplication()

注释:

// 动捕模式下CanSync=false. 各端自行计算Actor Location, client无需使用Server计算结果
// 自由行走模式下, CanSync=trueclient需要同步server的transform信息。

同步Attachment行为。主要是针对 不同角色执行不同的Attachment行为。 在AActor::OnRep_AttachmentReplication()的基础上添加:

	if (attachmentReplication.AttachParent)
	{
		if (RootComponent)
		{
			USceneComponent* AttachParentComponent = (attachmentReplication.AttachComponent ? attachmentReplication.AttachComponent : attachmentReplication.AttachParent->GetRootComponent());
			if (AttachParentComponent)
			{
				if(CanSync)
				{
					RootComponent->SetRelativeLocation_Direct(attachmentReplication.LocationOffset);
					RootComponent->SetRelativeRotation_Direct(attachmentReplication.RotationOffset);
					RootComponent->SetRelativeScale3D_Direct(attachmentReplication.RelativeScale3D);
				}
				
				// If we're already attached to the correct Parent and Socket, then the update must be position only.
				// AttachToComponent would early out in this case.
				// Note, we ignore the special case for simulated bodies in AttachToComponent as AttachmentReplication shouldn't get updated
				// if the body is simulated (see AActor::GatherMovement).
				const bool bAlreadyAttached = (AttachParentComponent == RootComponent->GetAttachParent() && attachmentReplication.AttachSocket == RootComponent->GetAttachSocketName() && AttachParentComponent->GetAttachChildren().Contains(RootComponent));
				if (bAlreadyAttached)
				{
					// Note, this doesn't match AttachToComponent, but we're assuming it's safe to skip physics (see comment above).
					if(CanSync)
					{
						RootComponent->UpdateComponentToWorld(EUpdateTransformFlags::SkipPhysicsUpdate, ETeleportType::None);
					}
				}
				else
				{
					BeforeAttachToNewParent();//
					RootComponent->AttachToComponent(AttachParentComponent, FAttachmentTransformRules::KeepRelativeTransform, attachmentReplication.AttachSocket);
					AfterAttachToNewParent();
				}
			}
		}
	}

TsIdolActor.ts

VirtualOverrider

CanSyncRelativeTransform(): boolean {
	if (Utils.HasTag(this.PropTags, new UE.GameplayTag("Idol.AIACao"))) {
		return false;
	}
	if(this.MovementComp && this.MovementComp.ManulMovement){
		return false
	}
	var animInstance = this.Mesh.GetAnimInstance() as UE.IdolAnimInstance
	let fullbodyNode = Reflect.get(animInstance, 'AnimGraphNode_Fullbody') as UE.AnimNode_FullBody
	return !(fullbodyNode && fullbodyNode.bGetMotionData)
}