에셋 매니저는 에디터와 패키지로 만든 게임에 고유한 글로벌 오브젝트
에셋을 개발자가 원하는 시점에 로드 및 언로드할 수 있는 기능을 지원, 게임을 배포할 때 쿠킹 및 청킹을 고려하여 에셋 최적화 가능.
기존 방법
에셋 매니저
FSoftObjectPath ItemPath = GetPrimaryAssetPath(PrimaryAssetId);
URPGItem* LoadedItem = Cast<URPGItem>(ItemPath.TryLoad());AssetManager.LoadPrimaryAsset(PrimaryAssetId, FStreamableDelegate::CreateUObject(this, &ThisClass::OnLoaded));언리얼에서 에셋 관리 시스템의 주된 타입으로 프라이머리 에셋과 세컨더리 에셋이 있다.
프라이퍼리 에셋 - 에셋 매니저가 직접 관리, 런타임 조작 가능 (ex. 아이템, 무기, 캐릭터)
세컨터리 에셋 - 프라이머리 에셋 내부에 포함 되거나 참조되는 추가 에셋, 에셋 매니저과 관리하지 않음 (ex. 스태틱 메시, 사운드)
프라이머리 에셋은 GetPrimaryAssetId 함수를 호출하여 프라이머리 에셋을 객체를 런타임에 직접 조작할 수 있음
// 아이템에서 PrimaryAssetID를 가져옴
FPrimaryAssetId PrimaryAssetId = MyItem->GetPrimaryAssetId();
// PrimaryAssetID에서 에셋 경로를 반환
FSoftObjectPath ItemPath = GetPrimaryAssetPath(PrimaryAssetId);
// 에셋 동기 로드
URPGItem* LoadedItem = Cast<URPGItem>(ItemPath.TryLoad());
UPrimaryDataAsset
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;DefaultEngine.ini에 커스텀 에셋매니저 등록[/Script/Engine.Engine]
AssetManagerClassName=/Script/Module.UClassName
ULyraAssetManager는 UAssetManager를 상속한 라이라 전용 에셋 관리 매니저
주요 기능
GetAsset과 GetSubclass 의 차이
데이터 에셋은 UObject기반의 데이터 에셋을 로드 (클래스 에셋은 불가능)
GetSubClass 함수를 정의하여 UClass 타입을 반환
UGameplayAbilityULyraAssetManager.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; // 접근 보호용
};
게임 전역에 공유되거나 재사용 되는 에셋 관리
세션이 바뀌어도 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);
...
}
GetAsset() 헬퍼 함수 - 로드된 에셋을 가져오는게 아닌 필요할 때 로드해서 반환if (UInputMappingContext* IMC = AssetManager.GetAsset(Entry.InputMapping))
{
Settings->RegisterInputMappingContext(IMC);
}GetSubClass()TSubclassOf<UGameplayEffect> DamageGE = ULyraAssetManager::GetSubclass(ULyraGameData::Get().DamageGameplayEffect_SetByCaller);