72 lines
3.0 KiB
Markdown
72 lines
3.0 KiB
Markdown
# 前言
|
||
继承关系: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=true,client需要同步server的transform信息。
|
||
|
||
同步Attachment行为。主要是针对 不同角色执行不同的Attachment行为。
|
||
在AActor::OnRep_AttachmentReplication()的基础上添加:
|
||
```c++
|
||
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
|
||
|
||
```typescript
|
||
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)
|
||
}
|
||
``` |