2024-05-16 17:18:33 +08:00
|
|
|
|
# 前言
|
2024-05-24 17:55:01 +08:00
|
|
|
|
继承关系:BP_XXX_Base -> BP_Idol_Base -> TsIdolActor -> AVCharacter -> ACharacter 。
|
2024-05-16 17:18:33 +08:00
|
|
|
|
主要逻辑位于TsIdolActor中,文件路径为`Script/LiveDirector/Character/TsIdolActor.ts`
|
|
|
|
|
|
2024-06-06 11:05:04 +08:00
|
|
|
|
# 添加新角色流程笔记
|
|
|
|
|
1. 添加一个Idol.xxx标签。
|
|
|
|
|
|
|
|
|
|
## 含有标签的文件
|
|
|
|
|
1. Ts_HandHelodCamUI.tsx
|
2024-06-07 12:32:19 +08:00
|
|
|
|
2. [ ] TsCharacterItem.ts `Script\LiveDirector\Character\View\TsCharacterItem.ts`
|
|
|
|
|
3. [ ] TsCharacterMocapViewTmp.ts :这个是MotionProcess的UI,继承控件`/Content/UIAssets/Character/Mocap/WBP_CharacterMocapViewTmp`
|
|
|
|
|
4. [ ] TsPropMocapItemTmp.ts
|
|
|
|
|
5. [ ] TsDirectorConsoleCommandHandler.ts
|
|
|
|
|
6. [ ] TsSpawnPointSettingItem.ts
|
|
|
|
|
7. [ ] TsIdolPropManagerComponent.ts
|
|
|
|
|
8. [ ] TsSimpleLevelManager.ts
|
|
|
|
|
9. ~~CameraDebug.cpp ~~(这个不需求)
|
2024-05-24 18:21:55 +08:00
|
|
|
|
# AVCharacter
|
|
|
|
|
主要实现了`virtual void OnRep_AttachmentReplication() override;`,声明了若干BlueprintNativeEvent:
|
|
|
|
|
- bool CanSyncRelativeTransform();
|
|
|
|
|
- void BeforeAttachToNewParent();
|
|
|
|
|
- void AfterAttachToNewParent();
|
|
|
|
|
|
|
|
|
|
## OnRep_AttachmentReplication()
|
|
|
|
|
注释:
|
|
|
|
|
>// 动捕模式下,CanSync=false. 各端自行计算Actor Location, client无需使用Server计算结果
|
2024-05-27 12:39:37 +08:00
|
|
|
|
// 自由行走模式下, CanSync=true,client需要同步server的transform信息。
|
2024-05-16 17:18:33 +08:00
|
|
|
|
|
2024-05-28 10:21:57 +08:00
|
|
|
|
同步Attachment行为。在AActor::OnRep_AttachmentReplication()的基础上添加:
|
2024-05-28 11:17:28 +08:00
|
|
|
|
- 判断CanSync标记,以此来决定是否同步Transform
|
|
|
|
|
- 未Attach组件=>Attch组件前后添加BeforeAttachToNewParent()、AfterAttachToNewParent()
|
2024-05-27 12:39:37 +08:00
|
|
|
|
```c++
|
2024-05-28 11:17:28 +08:00
|
|
|
|
auto CanSync = CanSyncRelativeTransform(); //获取Sync标记,具体的逻辑位于TsIdolActor.ts中
|
|
|
|
|
if (attachmentReplication.AttachParent)
|
|
|
|
|
{
|
|
|
|
|
if (RootComponent)
|
2024-05-27 12:39:37 +08:00
|
|
|
|
{
|
2024-05-28 11:17:28 +08:00
|
|
|
|
USceneComponent* AttachParentComponent = (attachmentReplication.AttachComponent ? attachmentReplication.AttachComponent : attachmentReplication.AttachParent->GetRootComponent());
|
|
|
|
|
if (AttachParentComponent)
|
2024-05-27 12:39:37 +08:00
|
|
|
|
{
|
2024-05-28 11:17:28 +08:00
|
|
|
|
if(CanSync)//增加判断Sync判断,只有在自由行走模式下才会同步Transform。
|
2024-05-27 12:39:37 +08:00
|
|
|
|
{
|
2024-05-28 11:17:28 +08:00
|
|
|
|
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)
|
2024-05-27 12:39:37 +08:00
|
|
|
|
{
|
2024-05-28 11:17:28 +08:00
|
|
|
|
RootComponent->UpdateComponentToWorld(EUpdateTransformFlags::SkipPhysicsUpdate, ETeleportType::None);
|
2024-05-27 12:39:37 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2024-05-28 11:17:28 +08:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
BeforeAttachToNewParent();//增加BlueprintNativeEvent
|
|
|
|
|
RootComponent->AttachToComponent(AttachParentComponent, FAttachmentTransformRules::KeepRelativeTransform, attachmentReplication.AttachSocket);
|
|
|
|
|
AfterAttachToNewParent();//增加BlueprintNativeEvent
|
|
|
|
|
}
|
2024-05-27 12:39:37 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2024-05-28 11:17:28 +08:00
|
|
|
|
}
|
2024-05-27 12:39:37 +08:00
|
|
|
|
```
|
2024-05-27 12:00:54 +08:00
|
|
|
|
|
2024-05-24 18:21:55 +08:00
|
|
|
|
# TsIdolActor.ts
|
|
|
|
|
## VirtualOverrider
|
2024-05-28 11:17:28 +08:00
|
|
|
|
CanSyncRelativeTransform()
|
|
|
|
|
- 不需要同步Transform的情况
|
|
|
|
|
- AI控制的ACao角色不需要同步。
|
|
|
|
|
- 使用TsIdolMovementComponent并且勾选了ManulMovement的情况不需要同步。
|
|
|
|
|
- 动画蓝图中使用了**AnimGraphNode_Fullbody**节点,并且bGetMotionData为true的情况不需要同步。
|
2024-05-24 18:21:55 +08:00
|
|
|
|
|
2024-05-28 11:17:28 +08:00
|
|
|
|
具体代码如下:
|
2024-05-24 18:21:55 +08:00
|
|
|
|
```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)
|
|
|
|
|
}
|
|
|
|
|
```
|