7.1 KiB
Raw Blame History

前言

继承关系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节点需要设置角色标签
  4. 指定用于修型的PostProcess动画蓝图。
  5. 添加Prop标签。
    1. Idol.XXX
    2. Prop.Dress
    3. Prop.MountPoint.Body
  6. 脚本扫描:点击编辑器的嘉然头像->角色道具配置全量生成 or 角色道具配置增量生成。会往IdolPropAssetConfig.json添加对应衣服或者道具配置数据。
  7. 设置道具挂载信息数据表ResArt/MountPointConfig/DT_MountPointConfig用于设置道具挂载时的相对偏移。
  8. 材质相关操作
    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. TsCharacterItem.ts Script/LiveDirector/Character/View/TsCharacterItem.ts
    1. 3级角色控制界面相关的UI操作。
  2. TsCharacterMocapViewTmp.ts :这个是MotionProcess的UI继承控件/Content/UIAssets/Character/Mocap/WBP_CharacterMocapViewTmp
    1. 在MotionProcess专用地图中创建对应的Idol。
  3. TsPropMocapItemTmp.ts
    1. 在MotionProcess专用地图中控制道具Attach到对应IdolUI逻辑
  4. TsDirectorConsoleCommandHandler.ts
    1. 快捷命令 Motion同步相关 GetMotionOffset
    2. 快捷命令 快速创建4个角色 IdolCostume
  5. TsSpawnPointSettingItem.ts
    1. IdolItemUI继承控件/Content/UIAssets/Character/WBP_SpawnPointSettingItem
  6. TsIdolPropManagerComponent.ts
    1. 没有思诺与心怡
    2. 需要搞清楚。
  7. 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()
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的情况不需要同步。

具体代码如下:

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()