149 lines
7.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 前言
继承关系BP_XXX_Base -> BP_Idol_Base -> TsIdolActor -> AVCharacter -> ACharacter 。
主要逻辑位于TsIdolActor中文件路径为`Script/LiveDirector/Character/TsIdolActor.ts`
# 添加新衣服流程
1. 在Content/Character/XXX中创建继承自BP_XXX_Base的蓝图。
2. 设置SkeletalMesh。并且确保勾选了**Dynamic InsetShadow**。
3. 添加PhysicalAsset并且保证胶囊体大致包裹模型否则阴影会出现被裁剪的问题。
4. 添加对应的OutlineMaterial。
5. 在DressName中输入新衣服的显示名称。
6. 添加Prop标签。
1. Idol.XXX
2. Prop.Dress(第一件衣服需要设置成Prop.Dress.Default)
3. Prop.MountPoint.Body
7. ***脚本扫描***:点击编辑器的嘉然头像->角色道具配置全量生成 or 角色道具配置增量生成。会往IdolPropAssetConfig.json添加对应衣服或者道具配置数据。
# 添加新角色流程笔记
1. 添加一个Idol.xxx标签。
2. 修改下面相关文件[[#含有角色标签的文件]]。
3. 添加对应的蓝图与文件结构。
1. Content/Character
1. 在Idol_Base中添加[[#BP_XXX_Base]]。
2. 设置衣服、头发的SkeletalMesh。并且确保勾选了**Dynamic InsetShadow**。
3. 添加角色、衣服、头发的PhysicalAsset并且保证胶囊体大致包裹模型否则阴影会出现被裁剪的问题。
2. Content/ResArt/CharacterArt放置角色与服装按照
1. 动画蓝图中的***FullBody节点需要设置角色标签***。
1. 指定用于修型的PostProcess动画蓝图。
2. 添加Prop标签。
1. Idol.XXX
2. Prop.Dress
3. Prop.MountPoint.Body
3. ***脚本扫描***:点击编辑器的嘉然头像->角色道具配置全量生成 or 角色道具配置增量生成。会往IdolPropAssetConfig.json添加对应衣服或者道具配置数据。
4. 设置道具挂载信息数据表ResArt/MountPointConfig/DT_MountPointConfig用于设置道具挂载时的相对偏移。
5. ***材质相关操作***
1. 在ResArt/CommonMaterial/Functions/CameraLightCollection中添加对应角色的属性。
2. 在ResArt/CommonMaterial/Functions/MF_CharacterMainLightIntensity中添加对应RoleID。
3. 在ResArt/CommonMaterial/Functions/MF_CharacterRimLightIntensity中添加对应RoleID。
4. 在对应角色的基础材质中设置RoleID数值。
5. 调用Python脚本制作Dissolve材质。LiveDirector/Editor/MaterialMigration/MakeDissolveMaterials.py
## 含有角色标签的文件
1. [x] TsCharacterItem.ts `Script/LiveDirector/Character/View/TsCharacterItem.ts`
1. 3级角色控制界面相关的UI操作。
2. [x] TsCharacterMocapViewTmp.ts :这个是MotionProcess的UI继承控件`/Content/UIAssets/Character/Mocap/WBP_CharacterMocapViewTmp`
1. 在MotionProcess专用地图中创建对应的Idol。
3. [x] TsPropMocapItemTmp.ts
1. 在MotionProcess专用地图中控制道具Attach到对应IdolUI逻辑
4. [x] TsDirectorConsoleCommandHandler.ts
1. 快捷命令 Motion同步相关 GetMotionOffset
2. 快捷命令 快速创建4个角色 IdolCostume
5. [x] TsSpawnPointSettingItem.ts
1. IdolItemUI继承控件`/Content/UIAssets/Character/WBP_SpawnPointSettingItem`
6. [x] TsIdolPropManagerComponent.ts
1. 没有思诺与心怡
2. 需要搞清楚。
7. [x] ~~TsSimpleLevelManager.ts~~
1. SwitchLiveArea()中调用只调用了Idol.BeiLa属于容错语句。
8. ~~CameraDebug.cpp ~~(这个不需求)
## BP_XXX_Base
1. 指定动画蓝图。
2. 指定LiveLinkName。
3. 指定OutlineMaterial。
# 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行为。在AActor::OnRep_AttachmentReplication()的基础上添加:
- 判断CanSync标记以此来决定是否同步Transform
- 未Attach组件=>Attch组件前后添加BeforeAttachToNewParent()、AfterAttachToNewParent()
```c++
auto CanSync = CanSyncRelativeTransform(); //获取Sync标记具体的逻辑位于TsIdolActor.ts中
if (attachmentReplication.AttachParent)
{
if (RootComponent)
{
USceneComponent* AttachParentComponent = (attachmentReplication.AttachComponent ? attachmentReplication.AttachComponent : attachmentReplication.AttachParent->GetRootComponent());
if (AttachParentComponent)
{
if(CanSync)//增加判断Sync判断只有在自由行走模式下才会同步Transform。
{
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();//增加BlueprintNativeEvent
RootComponent->AttachToComponent(AttachParentComponent, FAttachmentTransformRules::KeepRelativeTransform, attachmentReplication.AttachSocket);
AfterAttachToNewParent();//增加BlueprintNativeEvent
}
}
}
}
```
# TsIdolActor.ts
## VirtualOverrider
CanSyncRelativeTransform()
- 不需要同步Transform的情况
- AI控制的ACao角色不需要同步。
- 使用TsIdolMovementComponent并且勾选了ManulMovement的情况不需要同步。
- 动画蓝图中使用了**AnimGraphNode_Fullbody**节点并且bGetMotionData为true的情况不需要同步。
具体代码如下:
```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)
}
```
# Prop.Dress.Default
1. TsIdolPropManagerComponent.ts ServerLoadProp()
2. DoLoadProp()
3. ServerDoLoadPropPreset()
4. GetPropPreset()
5. GetDefaultDress()取得DefaultDress标签字符串。
6. GetPropAssetConfigsByTags(tags)根据标签取得对应的资产配置UPropAssetConfig
扫描所有资产TsPropAssetManager.ts CollectAllAssets()