Unreal Engine Lyra AssetManager 요약

LyraAssetManager 파일이 있다. 어떤 역할을 하는지 보도록 한다.

프로젝트에서 해당 파일을 확인할 수 있다.

ProjectMX
├─Source
│  └─LyraGames
│     └─System
│        ├─LyraAssetManager.cpp
│        └─LyraAssetManager.h (*)

LyraAssetManager.h 열기

ULyraAssetManager 클래스를 확인해보도록 한다.

해당 클래스는 public UAssetManager 으로부터 상속받고 있다. VS 2022 에서 확인하려면 Ctrl + 마우스 좌클릭으로 Unreal Engine 소스 파일로 이동한다.

public UAssetManager

주석으로 어떤 용도인지 적혀있다. 싱글톤 패턴으로 관리되고 있으며 중요한 에셋을 로딩하거나 로딩되지 않도록 한다. 그리고 에셋 레퍼런스를 유지하는 클래스이다.

즉, 싱글톤 매니저의 리소스 담당을 하고 있다.

LyraAssetManager.cpp

함수 ULyraAssetManager& ULyraAssetManager::Get()

ULyraAssetManager& ULyraAssetManager::Get()
{
	check(GEngine);

	if (ULyraAssetManager* Singleton = Cast<ULyraAssetManager>(GEngine->AssetManager))
	{
		return *Singleton;
	}

	UE_LOG(LogLyra, Fatal, TEXT("Invalid AssetManagerClassName in DefaultEngine.ini.  It must be set to LyraAssetManager!"));

	// Fatal error above prevents this from being called.
	return *NewObject<ULyraAssetManager>();
}

해당 코드에서 static ULyraAssetManager& Get(); Get 을 하면 에셋 싱글톤으로 반환하도록 하고있다.
자세히 들여다보면 ULyraAssetManager* Singleton = Cast(GEngine->AssetManager) GEngine->AssetManager 을 볼 수 있는데 GEngine->AssetManager 로 직접 가져오고 ULyraAssetManager 명시적 형변환된 싱글톤으로 반환한다.

GEngine->AssetManager 는 실제 언리얼 에디터에서 설정할 수 있다.

  • LyraAssetManager 로 사용하고 있으며 필요하다면 개발자가 자신이 만든 에셋 매니저를 넣어줘도 된다.
  • 다른 설정 방법은 Config 폴더 아래의 DefaultEngine.ini, DefaultGame.ini 에서 언리얼 에디터대신 설정할 수 있다.

UObject* ULyraAssetManager::SynchronousLoadAsset(const FSoftObjectPath& AssetPath)
경로를 가져와서 에셋을 로딩하는 코드도 있다.

중요한 것은 필요한 에셋을 메모리로 유지하다가 필요없어지면 메모리를 반환해주어야 한다.

private:
	
// Assets loaded and tracked by the asset manager.
UPROPERTY()
TSet<TObjectPtr<const UObject>> LoadedAssets;
  • LoadedAssets 로딩된 에셋을 겍체로 갖고있다.
class ULyraGameData : public UPrimaryDataAsset
{
	GENERATED_BODY()

public:

	ULyraGameData();

	// Returns the loaded game data.
	static const ULyraGameData& Get();

public:

	// Gameplay effect used to apply damage.  Uses SetByCaller for the damage magnitude.
	UPROPERTY(EditDefaultsOnly, Category = "Default Gameplay Effects", meta = (DisplayName = "Damage Gameplay Effect (SetByCaller)"))
	TSoftClassPtr<UGameplayEffect> DamageGameplayEffect_SetByCaller;

	// Gameplay effect used to apply healing.  Uses SetByCaller for the healing magnitude.
	UPROPERTY(EditDefaultsOnly, Category = "Default Gameplay Effects", meta = (DisplayName = "Heal Gameplay Effect (SetByCaller)"))
	TSoftClassPtr<UGameplayEffect> HealGameplayEffect_SetByCaller;

	// Gameplay effect used to add and remove dynamic tags.
	UPROPERTY(EditDefaultsOnly, Category = "Default Gameplay Effects")
	TSoftClassPtr<UGameplayEffect> DynamicTagGameplayEffect;
};
  • 스킬셋 이펙트로 관련된 코드
class LYRAGAME_API ULyraPawnData : public UPrimaryDataAsset
{
	GENERATED_BODY()

public:

	ULyraPawnData(const FObjectInitializer& ObjectInitializer);

public:

	// Class to instantiate for this pawn (should usually derive from ALyraPawn or ALyraCharacter).
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Lyra|Pawn")
	TSubclassOf<APawn> PawnClass;

	// Ability sets to grant to this pawn's ability system.
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Lyra|Abilities")
	TArray<TObjectPtr<ULyraAbilitySet>> AbilitySets;

	// What mapping of ability tags to use for actions taking by this pawn
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Lyra|Abilities")
	TObjectPtr<ULyraAbilityTagRelationshipMapping> TagRelationshipMapping;

	// Input configuration used by player controlled pawns to create input mappings and bind input actions.
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Lyra|Input")
	TObjectPtr<ULyraInputConfig> InputConfig;

	// Default camera mode used by player controlled pawns.
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Lyra|Camera")
	TSubclassOf<ULyraCameraMode> DefaultCameraMode;
};
  • ULyraPawnData 는 Pwan Data 에셋을 세부적으로 확인할 수 있는 코드
  • 객체 변수 이름들이 낯이 익을 것이다.
  • 이전에 Hero_WarriorGame 언리얼 에디터에서 데이터에셋을 만든 적이 있다.
  • 상속 받은 LyraPawnData 즉 앞에서 봤던 클래스임을 확인할 수 있다.
  • 에디터에서 데이터 파일을 만들고 연결하였다.
  • 연결한 파일은 런타임에 로딩하여 LyraAssetManager 객체변수로 들고 있는 형태이다.
const ULyraPawnData* ULyraAssetManager::GetDefaultPawnData() const
{
	return GetAsset(DefaultPawnData);
}
  • 다른 클래스에서 LyraPawnData 사용하고 싶다면 Getter 용도의 GetDefaultPawnData 불려오도록 한다.
// Global game data asset to use.
UPROPERTY(Config)
TSoftObjectPtr<ULyraGameData> LyraGameDataPath;

// Loaded version of the game data
UPROPERTY(Transient)
TMap<TObjectPtr<UClass>, TObjectPtr<UPrimaryDataAsset>> GameDataMap;

// Pawn data used when spawning player pawns if there isn't one set on the player state.
UPROPERTY(Config)
TSoftObjectPtr<ULyraPawnData> DefaultPawnData;
  • DefaultPawnData 는 LyraPawnData 데이터에서 아무것도 설정되지 않았을 때 가져오는 설정이라고 보면 된다.
  • DefaultPawnData 기본 설정은 UPROPERTY(Config) 코드로 인해 DefaultConfig.ini 파일에서 가져오고 있다.

ULyraPawnData 의 상속자 UPrimaryDataAsset

해당 UPrimaryDataAsset 주석에는 다음과 같이 적혀있다.

/**
 * A DataAsset that implements GetPrimaryAssetId and has asset bundle support, which allows it to be manually loaded/unloaded from the AssetManager.
 * Instances of native subclasses can be created directly as Data Assets in the editor and will use the name of the native class as the PrimaryAssetType.
 * Or, blueprint subclasses can be created to add variables and then subclassed again by Data Only Blueprints that set those variables.
 * With blueprint subclasses, use Data Only Blueprints (and not Data Asset instances) to properly handle data inheritance and updating the parent class.
 *
 * The PrimaryAssetType will be equal to the name of the first native class going up the hierarchy, or the highest level blueprint class.
 * IE, if you have UPrimaryDataAsset -> UParentNativeClass -> UChildNativeClass -> DataOnlyBlueprintClass the type will be ChildNativeClass.
 * Whereas if you have UPrimaryDataAsset -> ParentBlueprintClass -> DataOnlyBlueprintClass the type will be ParentBlueprintClass.
 * To change this behavior, override GetPrimaryAssetId in your native class or copy those functions into a different native base class.
 */
UCLASS(abstract, MinimalAPI, Blueprintable)
class UPrimaryDataAsset : public UDataAsset
  • 수동으로 로딩하고 언로딩하는 기능을 하고 있다. 이는 UDataAsset 기능인데, 이전 언리얼 에디터 실습에서 데이터 에셋 만들고 연결하는 과정을 해주도록 하는 클래스이다.
  • UPrimaryDataAsset 는 UDataAsset 기능을 제공하면서 확장된 기능이 있다.
    • 확장 기능으로 GetPrimaryAssetId 함수를 제공한다. 유니크 아이디를 부여하는 역할을 한다.
    • GetPrimaryAssetId 유니크값을 삽입하면 개발자가 에셋을 쉽게 로딩/언로딩을 유니크값을 통해 편리하게 사용할 수 있도록 한다.
    • 주석 will use the name of the native class as the PrimaryAssetType. 은 GetPrimaryAssetId 유니크 식별값이 PrimaryAssetType 을 가르킨다고 한다.
    • 소스코드에서의 GetPrimaryAssetId 은 LyraPawnData 의 식별자다.

GetPrimaryAssetId 설정 후 에셋들을 관찰 대상을 포함시키기

언리얼 에디터 Edit > Project Settings 를 열도록 한다.
Project Settings LNB 메뉴를 Game > Asset Manager 를 열도록 한다.

  • Lyra 공용으로 초기 로드되는 에셋들이 나열되어 있다.
  • Primary Asset Type 식별값 이름은 Asset Base Class 이름과 동일하다.
  • Directories 에셋의 경로로 스캔 범위로 둔다.
  • Specific Assets 경로가 아닌 특정 에셋을 스캔 범위로 둔다.

게임 배포 시 무분별하게 로드하면 사용자 리소스가 낭비되어 원활한 게임이 진행이 되지 않는다. 로드할 에셋 범위를 최소한으로 지정하도록 한다.

신규 개발 시..

신규 개발시 Lyra에서 앞서 본 코드와 유사하게 비슷한 코드를 만들어야 한다.

  • Experience 시작 시 Hero_WarriorGame를 구동하고
  • Hero_WarriorGame 안에 들은 Pawn.. 주인공들의 Mesh 파일들을 관리할 수 있도록 다른 객체를 만들도록 한다.