Post

UE - 라이라 Cosmetic 분석-1

UnrealEngine, Lyra

UE - 라이라 Cosmetic 분석-1

이번 팀프로젝트에선 모듈러 캐릭터를 이용할 예정이기에 라이라 코스메틱 부분을 분석해 봤다.

Cometic 관련 파일

라이라에서 사용하는 코스메틱 파일들

LyraCharacterPartTypes

LyraControllerComponent_CharacterParts

LyraCosmeticAnimationTypes

LyraCosmeticCheats

LyraCosmeticDeveloperSettings

LyraPawnComponent_CharacterParts

컴포넌트로 된 클래스들

LyraPawnComponent_CharacterParts 의 파생 블프는 B_MannequinnPawnCosmetics 1가지.

LyraControllerComponent_CharacterParts 파생 블프 B_CharacterSelection, B_PickRandomCharacter 2가지.

이 컨트롤러쪽은 플레이어 컨트롤러에 부착되어 사용되는 것을 저번에 확인했다.

때문에 액터에 붙어서 캐릭터 파츠를 부착하는 기능을 담당하는 것은 LyraPawnComponent_CharacterParts 로 예상한다.

LyraPawnComponent_CharacterParts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
UCLASS(meta=(BlueprintSpawnableComponent))  
class ULyraPawnComponent_CharacterParts : public UPawnComponent  
{  
    GENERATED_BODY()  
  
public:  
    ULyraPawnComponent_CharacterParts(const FObjectInitializer& ObjectInitializer = FObjectInitializer::Get());  
  
    //~UActorComponent interface  
    virtual void BeginPlay() override;  
    virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;  
    virtual void OnRegister() override;  
    //~End of UActorComponent interface  
  
    // Adds a character part to the actor that owns this customization component, should be called on the authority only    UFUNCTION(BlueprintCallable, BlueprintAuthorityOnly, Category=Cosmetics)  
    FLyraCharacterPartHandle AddCharacterPart(const FLyraCharacterPart& NewPart);  
  
    // Removes a previously added character part from the actor that owns this customization component, should be called on the authority only  
    UFUNCTION(BlueprintCallable, BlueprintAuthorityOnly, Category=Cosmetics)  
    void RemoveCharacterPart(FLyraCharacterPartHandle Handle);  
  
    // Removes all added character parts, should be called on the authority only  
    UFUNCTION(BlueprintCallable, BlueprintAuthorityOnly, Category=Cosmetics)  
    void RemoveAllCharacterParts();  
  
    // Gets the list of all spawned character parts from this component  
    UFUNCTION(BlueprintCallable, BlueprintPure=false, BlueprintCosmetic, Category=Cosmetics)  
    TArray<AActor*> GetCharacterPartActors() const;  
  
    // If the parent actor is derived from ACharacter, returns the Mesh component, otherwise nullptr  
    USkeletalMeshComponent* GetParentMeshComponent() const;  
  
    // Returns the scene component to attach the spawned actors to  
    // If the parent actor is derived from ACharacter, we'll use the Mesh component, otherwise the root component    USceneComponent* GetSceneComponentToAttachTo() const;  
  
    // Returns the set of combined gameplay tags from attached character parts, optionally filtered to only tags that start with the specified root  
    UFUNCTION(BlueprintCallable, BlueprintPure=false, BlueprintCosmetic, Category=Cosmetics)  
    FGameplayTagContainer GetCombinedTags(FGameplayTag RequiredPrefix) const;  
  
    void BroadcastChanged();  
  
public:  
    // Delegate that will be called when the list of spawned character parts has changed  
    UPROPERTY(BlueprintAssignable, Category=Cosmetics, BlueprintCallable)  
    FLyraSpawnedCharacterPartsChanged OnCharacterPartsChanged;  
  
private:  
    // List of character parts  
    UPROPERTY(Replicated, Transient)  
    FLyraCharacterPartList CharacterPartList;  
  
    // Rules for how to pick a body style mesh for animation to play on, based on character part cosmetics tags  
    UPROPERTY(EditAnywhere, Category=Cosmetics)  
    FLyraAnimBodyStyleSelectionSet BodyMeshes;  
};

이 폰 컴포넌트가 캐릭터에 캐릭터 파츠를 붙일 수 있는 기능을 제공하는 컴포넌트라고 생각한다.

캐릭터 파츠를 추가하는 함수

1
2
3
// Adds a character part to the actor that owns this customization component, should be called on the authority only  
UFUNCTION(BlueprintCallable, BlueprintAuthorityOnly, Category=Cosmetics)  
FLyraCharacterPartHandle AddCharacterPart(const FLyraCharacterPart& NewPart);

이게 캐릭터 파츠를 추가하는 함수다.

이건 서버에서만 호출이 가능하다고 한다.

저기서 반환하는 핸들이 캐릭터 파츠를 참조하는 핸들로 보인다.

1
2
3
4
FLyraCharacterPartHandle ULyraPawnComponent_CharacterParts::AddCharacterPart(const FLyraCharacterPart& NewPart)  
{  
    return CharacterPartList.AddEntry(NewPart);  
}

함수 내부는 이렇게 생겼다.

결국 캐릭터 파츠를 CharacterPartList에 추가하는 작업 뿐. 결국 CharacterPartList가 메인이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// A handle created by adding a character part entry, can be used to remove it later  
USTRUCT(BlueprintType)  
struct FLyraCharacterPartHandle  
{  
    GENERATED_BODY()  
  
    void Reset()  
    {  
       PartHandle = INDEX_NONE;  
    }  
  
    bool IsValid() const  
    {  
       return PartHandle != INDEX_NONE;  
    }  
  
private:  
    UPROPERTY()  
    int32 PartHandle = INDEX_NONE;  
  
    friend FLyraCharacterPartList;  
};

핸들의 내부 구조는 이렇다.

캐릭터 파츠를 관리하는 메인

1
2
UPROPERTY(Replicated, Transient)  
FLyraCharacterPartList CharacterPartList;

private 맴버 변수 중 하나다.

리플랙션으로 사용한 Replicated는 네트워크 복제 기능을 수행한다. 변수가 서버 -> 클라이언트로 동기화 되는 기능을 제공한다.

Transiendt는 휘발성 데이터라고 한다. 휘발성 데이터는 런타임에서만 유효하고 게임이 종료되면 사라지는 데이터라고 한다.

내일은 CharacterPartList 분석 내용을 정리해보겠다.

This post is licensed under CC BY 4.0 by the author.