본문 바로가기

언리얼 엔진 5

언리얼 엔진 5 런타임 에셋 로드/언로드 (Asset Manager & Primary Asset)

언리얼 엔진에서는 보통의 경우에 에셋이 자동으로 로드되고 언로드되는데, 에셋의 로드 / 언로드 시점을 제어하고 싶을 때가 있을 수 있다. (오픈월드와 같은 대규모 레벨에서의 최적화를 위해서라던가.)

 

이 때 사용하는 것이 바로 Asset ManagerPrimary Asset이다.

이를 간략하게 요약하면,

  • Asset Manager : Primary Asset을 처리하는 시스템
  • Primary Asset : Asset Manager에 의해 로드됨 (기본적으로 UWorld 레벨 에셋만이 Primary Asset)
  • Secondary Asset : Primary Asset 이외의 에셋들로, Primary Asset이 Secondary Asset을 참조하거나 사용하려는 경우에 엔진에서 자동으로 처리하는 에셋

요컨대, 로드 시점을 컨트롤하고 싶은 Secondary Asset을 Primary Asset으로 만들어버리면 된다는 것이다.

 

그 방법은 UObject에 존재하는 GetPrimaryAssetId()를 내가 원하는 에셋의 클래스에 오버라이드 해주는 것이다.

 

UCLASS()
class OPENWORLDTPCPP_API UDLCDataAsset : public UPrimaryDataAsset
{
	GENERATED_BODY()
	
public:
    UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "DLC")
    FName DLCName;

	virtual FPrimaryAssetId GetPrimaryAssetId() const override
	{
		FName PrimaryAssetName = FPackageName::GetShortFName(GetOutermost()->GetName());
		return FPrimaryAssetId("DLC", PrimaryAssetName);
	}
};

 

 

예시 코드에서는, "DLC"라는 Primary Asset Type에, 블루프린트 클래스의 이름이 Primary Asset Name으로 들어가게 설정되어 있다.

 

DLCDataAsset을 부모 클래스로 두는 블루프린트 클래스의 모습

 

 

원하는 에셋을 Primary Asset으로 변경했다고 끝나는 것은 아니다.

 

Primary Asset을 관리하는 주체인 Asset Manager가 Primary Asset을 스캔할 수 있도록 추가 작업이 필요하다.

 

 

 

1. 프로젝트 세팅의 Asset Manager에서 Primary Asset의 Type을 직접 추가해준다.

 

UCLASS(Blueprintable)
class OPENWORLDTPCPP_API UDLCAssetManager : public UAssetManager
{
	GENERATED_BODY()
	
public:
	virtual void StartInitialLoading() override;
};

 

void UDLCAssetManager::StartInitialLoading()
{
    Super::StartInitialLoading();

    UAssetManager& AssetManager = UAssetManager::Get();
    const FPrimaryAssetType DLCAssetType = FPrimaryAssetType("DLC");
    FString DLCPath = TEXT("/Game/DLC");

    AssetManager.ScanPathForPrimaryAssets(DLCAssetType, DLCPath, UDLCDataAsset::StaticClass(), true);
}

 

2-1. UAssetManager를 상속받는 커스텀 Asset Manager를 구현한 뒤 원하는 Primary Asset 스캔 과정을 추가한다.

 

 

2-2. 그 후에, Asset Manager Class를 커스텀 Asset Manager로 교체해준다.

 

다양한 Primary Asset을 주도적으로 사용할 것이라면 아예 속편하게 커스텀 Asset Manager를 만드는 후자의 방법이 더 나을 수 있을 것으로 보인다.

 

 

여기까지의 작업이 끝났다면, 이제 원하는 타이밍에 Primary Asset을 로드하는 일만 남았다.

 

void UDLCAssetManager::LoadDLC(FName DLCID)
{
    UAssetManager& AssetManager = UAssetManager::Get();
    FPrimaryAssetId PrimaryAssetId = FPrimaryAssetId("DLC", DLCID);

    AssetManager.LoadPrimaryAsset(PrimaryAssetId, {}, FStreamableDelegate::CreateLambda([DLCID]()
    {
        UE_LOG(LogTemp, Log, TEXT("DLC %s Loaded!"), *DLCID.ToString());
    }));
}

 

Primary Asset의 언로드가 필요하다면, 비슷한 방법으로 UnloadPrimaryAsset을 호출하면 된다.

 

 

참고 문서

https://dev.epicgames.com/documentation/ko-kr/unreal-engine/asset-management-in-unreal-engine