언리얼 C++ 프로그래밍

[언리얼 C++] Asset 레지스트리

언린이 2021. 6. 20. 20:10

Asset 레지스트리는 에디터가 로드되면서 로드되지 않은 Asset에 대한 정보를 비동기적으로 모으는 에디터 서브시스템입니다. 이 정보는 에디터가 Asset을 로드하지 않고 목록을 만들 수 있도록 메모리에 저장됩니다. 이 정보는 메모리의 Asset이나 디스크의 파일이 변경되면 최신으로 자동 유지됩니다.

 

 

1. Asset 목록 구하기

클래스별 Asset 목록을 만들려면, Asset 레지스트리 모듈을 로드한 다음 Module.Get().GetAssetsByClass() 함수를 부르기만 하면 됩니다.

FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<FAssetRegistryModule>("AssetRegistry");
TArray<FAssetData> AssetData;
const UClass* Class = UStaticMesh::StaticClass();
AssetRegistryModule.Get().GetAssetsByClass(Class, AssetData);

이러면 Asset의 로드/언로드 여부를 기술하는 FAssetData 오브젝트 목록을 반환합니다. FAssetData 오브젝트는 Asset 로드 전에 결정 가능한 정보를 담습니다.

 

클래스별 Asset 목록 말고도 다른 범주별 목록을 만들 수도 있습니다.

- GetAssetsByPackageName() : 특정 패키지의 Asset 목록을 반환합니다.

- GetAssetsByPath() : 지정된 경로의 Asset 목록을 반환합니다.

- GetAssetByObjectPath() : 지정된 오브젝트 경로의 Asset 목록을 반환합니다.

- GetAssetsByTagValues() : 지정된 태그와 값 세트의 Asset 목록을 반환합니다.

- GetAllAssets() : 모든 Asset 목록을 반환합니다.

 

또한, Asset 목록을 구한 다음 FAssetData의 사용을 위해서 UObject* 타입으로 변환할 필요가 있을 수 있습니다.

FAssetData 오브젝트는 자신이 나타내는 UObject*를 반환하는 함수 GetAsset()을 가지고 있어서 해당 함수를 사용하면 됩니다. 마지막으로 Asset이 로드되었는지 확인만 하려면, IsAssetLoaded() 함수를 사용합니다.

 

 

2. 필터 만들기

GetAssets()를 부를때 FARFilter를 제공하여 여러 범주별로 필터링되는 Asset 목록을 만들 수 있습니다.

필터는 여러가지 Component로 구성되어져 있는데, PackageName, PackagePath, Collection, Class, Tags/Value 짝이 존재합니다.

Asset은 필터의 모든 Component를 만족해야 통과할 수 있습니다.

 

아래는 Class와 PackagePath, Component가 둘인 필터 사용의 예제입니다.

FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<FAssetRegistryModule>("AssetRegistry");
TArray<FAssetData> AssetData;
FARFilter Filter;
Filter.Classes.Add(UStaticMesh::StaticClass());
Filter.PackagePaths.Add("/Game/Meshes");
AssetRegistryModule.Get().GetAssets(Filter, AssetData);

 

 

3. 태그와 값

Asset 레지스트리에서 반환된 FAssetData 오브젝트에는 TagsAndValues라는 태그와 값의 매핑에 대한 객체가 들어있습니다. 이것은 FAssetData가 나타내는 Asset의 프로퍼티 값과 연관된 값의 목록입니다. 이 정보는 Asset이 저장되어 Asset이 들어있는 UAsset 파일의 헤더에 기록될 때 수집됩니다. Asset 레지스트리는 이 헤더를 읽은 다음 그에 맞게 TagsAndValues 맵을 채웁니다. Asset 레지스트리는 AssetRegistrySearchable UPROPERTY() 플래그로 마킹된 프로퍼티만 모읍니다.

 

UPROPERTY(Category=Texture, AssetRegistrySearchable)
TEnumAsByte<enum TextureFilter> Filter;

이 플래그가 UTexture의 Filter 프로퍼티에 추가되고 나면, 이제 그 이후로 저장되는 모든 UTexture는 그 FAssetData의 TagsAndValues 맵에 항목이 생성되며, 그 키는 Filter이고 그 값은 "TF_Linear" 처럼 enum 값의 문자열 표현입니다.

 

 

4. 비동기 데이터 수집

Asset 레지스트리는 UAsset 파일을 비동기식으로 읽기 때문에, Asset 목록을 요청한 시간에 모든 Asset 목록이 존재하지 않을 수도 있습니다. 에디터 코드에서 전체 목록을 요청하면, Asset 레지스트리는 Asset이 언제 발견/생성, 이름 변경, 제거되었는가에 대한 델리게이트 콜백을 제공합니다. Asset 레지스트리가 초기 검색을 완료한 시점에 대한 델리게이트도 있는데, 여러 시스템에 유용합니다.

 

Asset 레지스트리 모듈을 로드한 다음 IAssetRegistry에 제공된 함수를 사용하여 아래 델리게이트에 등록하면 됩니다.

/** 레지스트리에 애셋이 추가될 때에 대한 콜백을 등록/해제합니다.  */
virtual FAssetAddedEvent& OnAssetAdded() = 0;

/** 레지스트리에서 애셋이 제거될 때에 대한 콜백을 등록/해제합니다. */
virtual FAssetRemovedEvent& OnAssetRemoved() = 0;

/** 레지스트리에 애셋 이름이 변경될 때에 대한 콜백을 등록/해제합니다. */
virtual FAssetRenamedEvent& OnAssetRenamed() = 0;

/** 애셋 레지스트리가 파일 로드를 완료했을 때에 대한 콜백을 등록/해제합니다. */
virtual FFilesLoadedEvent& OnFilesLoaded() = 0;

/** 백그라운드 파일 로드 진행상황 업데이트를 위한 콜백을 등록/해제합니다. */
virtual FFileLoadProgressUpdatedEvent& OnFileLoadProgressUpdated() = 0;

/** 현재 애셋 레지스트리가 파일을 로드중이라 모든 애셋에 대해 알지 못하면 참을 반환합니다. */
virtual bool IsLoadingAssets() = 0;

 

아래는 해당 델리게이트에 함수를 등록하는 예제입니다.

void FMyClass::FMyClass()
{
    // 업데이트 감지를 위해 Asset 레지스트리 모듈을 로드합니다.
    FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<FAssetRegistryModule>("AssetRegistry");
    AssetRegistryModule.Get().OnAssetAdded().AddRaw( this, &FMyClass::OnAssetAdded );
}

FMyClass::~FMyClass()
{
    // 델리게이트 등록해제를 위해 Asset 레지스트리 모듈을 로드합니다.
    FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<FAssetRegistryModule>("AssetRegistry");
    AssetRegistryModule.Get().OnAssetAdded().RemoveAll( this );
}

void FMyClass::OnAssetAdded(const FAssetData& AssetData)
{
    // Asset 레지스트리가 Asset을 발견하면 이 함수가 실행됩니다.
    // Asset이 발견된 후 실행되어야 할 내용을 작성합니다.
}