Lyra Cosmetic换装逻辑

<meta charset="utf-8">

快速开始

https://www.bilibili.com/video/BV19B4y1L7Cm/?spm_id_from=333.337.search-card.all.click&vd_source=f91b86a9db5d272fcc792e207e0f6f89

原理实现步骤

  1. 逻辑实体

逻辑实体拥有完整的Character所有逻辑。只是SkeletonMesh里面的角色是一个只有骨架没有网格Mesh的角色。

image.png

2.时装蓝图。只有一个SkeletonMesh


image.png
  1. 点击换装的时候,通过LyraPawnComponent_CharacterParts来Spawn出来一个BP_Actor。并且Attachment到该角色Actor下面。
image.png
  1. 通过IKRig和IK Retargeting进行两个SkeletonMesh的动画同步
image.png

核心实现代码

bool FLyraCharacterPartList::SpawnActorForEntry(FLyraAppliedCharacterPartEntry& Entry)
{
    bool bCreatedAnyActors = false;

    if (ensure(OwnerComponent) && !OwnerComponent->IsNetMode(NM_DedicatedServer))
    {
       if (Entry.Part.PartClass != nullptr)
       {
          UWorld* World = OwnerComponent->GetWorld();

          if (USceneComponent* ComponentToAttachTo = OwnerComponent->GetSceneComponentToAttachTo())
          {
             const FTransform SpawnTransform = ComponentToAttachTo->GetSocketTransform(Entry.Part.SocketName);

             UChildActorComponent* PartComponent = NewObject<UChildActorComponent>(OwnerComponent->GetOwner());

             PartComponent->SetupAttachment(ComponentToAttachTo, Entry.Part.SocketName);
             PartComponent->SetChildActorClass(Entry.Part.PartClass);
             PartComponent->RegisterComponent();

             if (AActor* SpawnedActor = PartComponent->GetChildActor())
             {
                switch (Entry.Part.CollisionMode)
                {
                case ECharacterCustomizationCollisionMode::UseCollisionFromCharacterPart:
                   // Do nothing
                   break;

                case ECharacterCustomizationCollisionMode::NoCollision:
                   SpawnedActor->SetActorEnableCollision(false);
                   break;
                }

                // Set up a direct tick dependency to work around the child actor component not providing one
                if (USceneComponent* SpawnedRootComponent = SpawnedActor->GetRootComponent())
                {
                   SpawnedRootComponent->AddTickPrerequisiteComponent(ComponentToAttachTo);
                }
             }

             Entry.SpawnedComponent = PartComponent;
             bCreatedAnyActors = true;
          }
       }
    }

    return bCreatedAnyActors;
}

GM相关开发

UCheatManager

GM指令调用换装逻辑。查看源代码的时候看到这个类很有意思,用来实现UE的GM指令相关的逻辑类。

https://zhuanlan.zhihu.com/p/553937135

/** Cheats related to bots */
UCLASS(NotBlueprintable)
class ULyraCosmeticCheats final : public UCheatManagerExtension
{
    GENERATED_BODY()

public:
    ULyraCosmeticCheats();

    // Adds a character part
    UFUNCTION(Exec, BlueprintAuthorityOnly)
    void AddCharacterPart(const FString& AssetName, bool bSuppressNaturalParts = true);

    // Replaces previous cheat parts with a new one
    UFUNCTION(Exec, BlueprintAuthorityOnly)
    void ReplaceCharacterPart(const FString& AssetName, bool bSuppressNaturalParts = true);

    // Clears any existing cheats
    UFUNCTION(Exec, BlueprintAuthorityOnly)
    void ClearCharacterPartOverrides();

private:
    ULyraControllerComponent_CharacterParts* GetCosmeticComponent() const;
};
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容