에셋 매니저(AssetManager)

조정원·2025년 10월 30일

✅ 에셋 매니저

에셋 매니저는 에디터와 패키지로 만든 게임에 고유한 글로벌 오브젝트

에셋을 개발자가 원하는 시점에 로드 및 언로드할 수 있는 기능을 지원, 게임을 배포할 때 쿠킹 및 청킹을 고려하여 에셋 최적화 가능.

기존 방법

  • 블루 프린트 또는 C++에서 에셋을 참조하면 기존 에셋을 패키지 로드 시점에 자동으로 로드
  • 동기/비동기 로드가 가능하지만, 관리가 어렵고 어떤 에셋이 로드 완료 되었는지 추적 필요

에셋 매니저

  • 프라이머리/세컨더리 에셋 - 로드 및 언로드 시점 제어
  • 동기/비동기 로드
    • 동기적 로드
      FSoftObjectPath ItemPath = GetPrimaryAssetPath(PrimaryAssetId);
      URPGItem* LoadedItem = Cast<URPGItem>(ItemPath.TryLoad());
    • 비동기적 로드 - 완료시 콜백으로 처리
      AssetManager.LoadPrimaryAsset(PrimaryAssetId, FStreamableDelegate::CreateUObject(this, &ThisClass::OnLoaded));
  • AssetBundle/Chunk 단위로 관리 가능
  • 스트리밍 관리와 연계 가능

✅ 프라이머리 에셋

언리얼에서 에셋 관리 시스템의 주된 타입으로 프라이머리 에셋과 세컨더리 에셋이 있다.

프라이퍼리 에셋 - 에셋 매니저가 직접 관리, 런타임 조작 가능 (ex. 아이템, 무기, 캐릭터)

세컨터리 에셋 - 프라이머리 에셋 내부에 포함 되거나 참조되는 추가 에셋, 에셋 매니저과 관리하지 않음 (ex. 스태틱 메시, 사운드)

프라이머리 에셋은 GetPrimaryAssetId 함수를 호출하여 프라이머리 에셋을 객체를 런타임에 직접 조작할 수 있음

// 아이템에서 PrimaryAssetID를 가져옴
FPrimaryAssetId PrimaryAssetId = MyItem->GetPrimaryAssetId();

// PrimaryAssetID에서 에셋 경로를 반환
FSoftObjectPath ItemPath = GetPrimaryAssetPath(PrimaryAssetId);

// 에셋 동기 로드
URPGItem* LoadedItem = Cast<URPGItem>(ItemPath.TryLoad());

프라이머리 에셋 생성

UPrimaryDataAsset

  • UDataAsset의 자손 클래스
  • 에셋 번들 로드/저장 기능
  • 예시
    UCLASS()
    class ACTIONRPG_API URPGItem : public UPrimaryDataAsset
    {
    	GENERATED_BODY()
    
    public:
    	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Item)
    	FPrimaryAssetType ItemType;
    
    	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Item)
    	FText ItemName;
    	
    	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Item)
    	FSlateBrush ItemIcon;
    	
    	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Max)
    	int32 MaxLevel;

프라이머리 에셋 등록

  1. 커스텀 에셋 매니저 클래스 생성
  2. DefaultEngine.ini에 커스텀 에셋매니저 등록
[/Script/Engine.Engine]
AssetManagerClassName=/Script/Module.UClassName
  1. 프라이머리 에셋 스캔 경로 설정 (ProjectSettings/Game/AssetManager)

✅ 라이라 샘플

ULyraAssetManagerUAssetManager를 상속한 라이라 전용 에셋 관리 매니저

주요 기능

  • 싱글톤으로 어디서든 접근 가능
  • SoftObjectPtr/TSoftClassPtr 기반 동기 로딩 지원
  • 로드된 에셋을 추적하여 GC 방지
  • 스타트업 잡 관리, 초기화 로직 집중
  • 게임 데이터 및 기본 Pawn 데이터 타입 안전하게 로드
  • 에디터/런타임 로딩 환경 구분

GetAssetGetSubclass 의 차이

  • 데이터 에셋은 UObject기반의 데이터 에셋을 로드 (클래스 에셋은 불가능)

  • GetSubClass 함수를 정의하여 UClass 타입을 반환

    • UClass 기반의 블루프린트 클래스를 로드
    • 클래스 정의만 메모리에 로드
    • ex. UGameplayAbility

    ULyraAssetManager.h

class LYRAGAME_API ULyraAssetManager : public UAssetManager
{
	GENERTED_BODY();
public:
	ULYRAssetManager(); // 생성자
	
	static ULyraAssetManager& Get(); // 싱글톤 접근
	
	template<typename AssetType>
	static AssetType* GetAsset(...); // 에셋 동기 로드 (UObject)
	
	template<typename AssetType>
	static AssetType* GetSubclass(...); // 에셋 동기 로드 (UClass)
	
	static void DumpLoadedAssets(); // 디버깅용 Logging
	
	const ULyraGameData& GetGameData(); // 데이터 접근자 (GameData)
	const ULyraPawnData* GetDefaultPawnData() const; // 데이터 접근자 (PawnData)
	
protected:
	template <typename GameDataClass>
	const GameDataClass& GetOrLoadTypedGameData(...); // GameData 로드 또는 반환
	
	static UObject* SynchronousLoadAsset(...); // 내부 로드 함수
	static bool ShouldLogAssetLoads(); // 로드 시점 디버깅 로그 출력 제어
	
	void AddLoadedAsset(...); // 로드된 에셋 등록 (캐싱 관리)
	
	virtual void StartInitialLoading() override; // 초기 로딩 재정의
	#if WITH_EDITOR
	virtual void PreBeginPIE(...) override; // 에디터용 처리
	#endif
	
	UPrimaryDataAsset* LoadGameDataOfClass(...); // 전용 GameData 로드
	
protected:
	TSoftObjectPtr<ULyraGameData> LyraGameDataPath;
	
	TMap<TObjectPtr<UClass>, TObjectPtr<UPrimaryDataAsset>> GameDataMap;
	
	TSoftObjecPtr<ULyraPawnData> DefaultPawnData;
	
protected:

	void DoAllStartupJobs(); // 초기화 관련
	
	void InitializeGameplayCueManager(); // GamePlayCue 시스템 초기화
	
	void UpdateInitialGameContentLoadPercent(...); // 로딩 퍼센트 갱신
	
	TArray<FLyraAssetManagerStartupJobs> StartupJobs; // 초기 적업 리스트
	
private:
	TSet<TObjectPtr<const UObject>> LoadedAssets; // 로드된 에셋
	
	FCriticalSection LoadedAssetsCritical; // 접근 보호용
	
};
  • 사용 예시 1: 라이라 경험 설정

    AssetManager vs ExperienceManager

    ULyraAssetManager
    • 게임 전역에 공유되거나 재사용 되는 에셋 관리

    • 세션이 바뀌어도 GC로 자동 해제되면 안 됨

      UExperienceManagerComponent

    • 현재 플레이 중인 경험에 필요한 에셋만 로드

    • AssetManger가 직접 관리하지 않음

    • CurrentExperience 에 경험을 저장

    • 경험이 바뀌거나 종료 될 때 참조 해제

    • Experience 로드 → Exeperience 실행 → Experience 종료 → 참조 해제(GC 대상)

      void ULyraExperienceManagerComponent::SetCurrentExperience(FPrimaryAssetId ExperienceId)
      {
      	ULyraAssetManager& AssetManager = ULyraAssetManager::Get();
      	FSoftObjectPath AssetPath = AssetManager.GetPrimaryAssetPath(ExperienceId);
      	TSubclassOf<ULyraExperienceDefinition> AssetClass = Cast<UClass>(AssetPath.TryLoad());
      	check(AssetClass);
      	const ULyraExperienceDefinition* Experience = GetDefault<ULyraExperienceDefinition>(AssetClass);
      
      	...
      }
  • 사용 예시2: GetAsset() 헬퍼 함수 - 로드된 에셋을 가져오는게 아닌 필요할 때 로드해서 반환
    if (UInputMappingContext* IMC = AssetManager.GetAsset(Entry.InputMapping))
    {
    	Settings->RegisterInputMappingContext(IMC);
    }
  • 사용 예시3: GetSubClass()
    TSubclassOf<UGameplayEffect> DamageGE = ULyraAssetManager::GetSubclass(ULyraGameData::Get().DamageGameplayEffect_SetByCaller);
profile
게임 AI 개발자 조정원입니다.

0개의 댓글