에셋 레지스트리 (Asset Registry)는 에디터가 로드되면서 로드되지 않은 에셋에 대한 정보를 비동기적으로 그러모으는 에디터 서브시스템입니다. 이 정보는 에디터가 에셋을 로드하지 않고 목록을 만들 수 있도록 메모리에 저장됩니다. 이 정보는 권위적(authoritative)이며, 메모리의 에셋이나 디스크의 파일이 변경되면 최신으로 자동 유지됩니다. 이 시스템의 주요 고객은 콘텐츠 브라우저이지만, 에디터 코드의 어디에서도 사용될 수 있습니다.
에셋 목록 구하기
클래스별 에셋 목록을 만들려면, 에셋 레지스트리 모듈을 로드한 다음 Module.Get().GetAssetsByClass()
을 부르기(invoke)만 하면 됩니다.
FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<FAssetRegistryModule>("AssetRegistry");
TArray<FAssetData> AssetData;
const UClass* Class = UStaticMesh::StaticClass();
AssetRegistryModule.Get().GetAssetsByClass(Class->GetFName(), AssetData);
그러면 에셋의 로드/언로드 여부를 기술하는 FAssetData
오브젝트 목록을 반환합니다.
FAssetData
오브젝트는 에셋 로드 전에 결정 가능한 정보를 담습니다.
그 멤버와 설명은 이렇습니다:
멤버 | 설명 |
---|---|
FName ObjectPath |
에셋에 대한 Package.GroupNames.AssetName 형태의 오브젝트 경로입니다. |
FName PackageName |
에셋이 들어있는 패키지 이름입니다. |
FName PackagePath |
에셋이 들어있는 패키지 경로입니다. |
FName GroupNames |
에셋이 들어있는 그룹 이름 목록은 '. ' 으로 구분합니다. 그룹이 없으면 NAME_None 입니다. |
FName AssetName |
패키지나 그룹을 뺀 에셋 이름입니다. |
FName AssetClass |
에셋의 클래스 이름입니다. |
TMap<FName, FString> TagsAndValues |
AssetRegistrySearchable (검색가능 에셋 레지스트리) 마킹된 프로퍼티에 대한 값 매핑입니다. 자세한 정보는 태그와 값 부분을 참고하시기 바랍니다. |
다음 함수 중 하나를 불러 다른 범주별 목록을 만들 수도 있습니다:
함수 | 설명 |
---|---|
GetAssetsByPackageName() |
특정 패키지의 에셋 목록을 반환합니다. |
GetAssetsByPath() |
지정된 경로의 에셋 목록을 반환합니다. |
GetAssetByObjectPath() |
지정된 오브젝트 경로의 에셋 목록을 반환합니다. |
GetAssetsByTagValues() |
지정된 태그와 값 세트의 에셋 목록을 반환합니다. |
GetAllAssets() |
모든 에셋 목록을 반환합니다. 느릴 수 있습니다. |
여러 범주를 사용하여 에셋 목록을 만들 필요가 있다면, 필터 만들기 부분대로 GetAssets()
에 FARFilter
구조체를 사용하면 됩니다.
FAssetData 를 UObject* 로 변환하기
FAssetData
오브젝트는 FAssetData
가 나타내는 UObject*
를 반환하는 함수
GetAsset()
이 있습니다. 필요한 에셋을 로드한 다음 반환합니다.
에셋이 로드되었는지 확인만 하려면, IsAssetLoaded()
를 사용합니다.
필터 만들기
GetAssets()
를 부를 때 FARFilter
를 제공하여 여러 범주별로 필터링되는 에셋 목록을
만들 수 있습니다. 필터는 여러 컴포넌트로 구성됩니다:
- PackageName
- PackagePath
- Collection
- Class
- Tags/Value 쌍
하나의 컴포넌트(component)에는 요소(element)가 하나 이상일 수 있습니다. 에셋은 필터의 모든 컴포넌트 를 충족시켜야 통과입니다. 하나의 컴포넌트를 충족시키려면, 에셋은 그 안의 요소 아무것에나 일치하면 됩니다.
/Game/Meshes/BeachBall 경로에 존재하는 StaticMesh 에셋을 예로 들면:
- PackagePath 는
/Game/Meshes
인 필터에 이 에셋은 통과입니다. 요소가 하나인 컴포넌트 딱 하나입니다. - PackagePath 는
/Game/Meshes
, Class 는UParticleSystem
ANDUStaticMesh
인 필터에 이 에셋은 통과입니다. 컴포넌트가 둘이며, 첫째 컴포넌트에는 요소가 하나, 둘째 컴포넌트에는 요소가 둘 있습니다. - PackagePath 는
/Game/Meshes
, Class 는UParticleSystem
뿐인 필터에 이 에셋은 통과하지 못합니다. 요소가 각각 하나씩인 컴포넌트가 둘 입니다. - PackagePath 는
/Game/NotMeshes
, Class 는UStaticMesh
인 필터에 이 에셋은 통과하지 못합니다. 이 필터 역시 요소가 각각 하나씩인 컴포넌트가 둘 입니다.
Class 와 PackagePath, 컴포넌트가 둘인 필터 사용 예입니다:
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);
태그와 값
에셋 레지스트리에서 반환된 FAssetData
오브젝트에는 TagsAndValues
라는 이름과 값 매핑이 들어있습니다.
이것은 FAssetData
가 나타내는 에셋의 프로퍼티 값과 연관된 값의 목록입니다.
이 정보는 에셋이 저장되어 에셋이 들어있는 UAsset
파일의 헤더에 기록될 때 수집됩니다.
에셋 레지스트리는 이 헤더를 읽은 다음 그에 맞게 TagsAndValues
맵을 채웁니다.
에셋 레지스트리는 AssetRegistrySearchable
UPROPERTY()
플래그로 마킹된 프로퍼티만 모읍니다.
예를 들어 (UTexture
에서):
/** 이 텍스처를 샘플링할 때 사용할 텍스처 필터링 모드입니다. */
UPROPERTY(Category=Texture, AssetRegistrySearchable)
TEnumAsByte<enum TextureFilter> Filter;
이 플래그가 UTexture
의 'Filter' 프로퍼티에 추가되고 나면, 이제 그 이후로 저장되는 모든 UTexture
는 그 FAssetData
의 TagsAndValues
맵에 항목이 생성되며, 그 키는 "Filter"
이고 그 값은 "TF_Linear"
처럼 enum 값의 문자열 표현입니다.
이 에셋을 다시 저장 해야 에셋 레지스트리가 그 프로퍼티를 발견할 수 있습니다.
에셋 레지스트리가 UProperty 직계가 아닌 정보를 검색할 수 있도록 하려면, 에셋의 클래스에서 가상 함수 GetAssetRegistryTags() 를 구현하여 TagsAndValues 맵에 키/값 짝을 수동으로 추가해 주면 됩니다. GetAssetRegistryTags 는 UObject 를 상속받습니다.
비동기 데이터 수집
에셋 레지스트리는 UAsset
파일을 비동기식으로 읽기에, 요청한 시간에 모든 에셋 목록 전체가
없을 수도 있습니다. 에디터 코드에서 전체 목록을 요청하면, 에셋 레지스트리는 에셋이 언제
발견/생성, 이름변경, 제거되었는가에 대한 델리게이트 콜백을 제공합니다. 에셋 레지스트리가
초기 검색을 완료한 시점에 대한 델리게이트도 있는데, 여러 시스템에 유용합니다.
에셋 레지스트리 모듈을 로드한 다음 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()
{
// 업데이트 감지를 위해 에셋 레지스트리 모듈을 로드합니다.
FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<FAssetRegistryModule>("AssetRegistry");
AssetRegistryModule.Get().OnAssetAdded().AddRaw( this, &FMyClass::OnAssetAdded );
}
FMyClass::~FMyClass()
{
// 델리게이트 등록해제를 위해 에셋 레지스트리 모듈을 로드합니다.
FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<FAssetRegistryModule>("AssetRegistry");
AssetRegistryModule.Get().OnAssetAdded().RemoveAll( this );
}
void FMyClass::OnAssetAdded(const FAssetData& AssetData)
{
// 에셋 레지스트리가 에셋을 발견했습니다.
// 즉 방금 생성되었거나 방금 디스크에서 찾았다는 뜻입니다.
// 이 함수의 코드가 빠른지 확인, 아니면 수집 프로세스가 늦춰집니다.
}
에셋 레지스트리는 커맨드렛 에 사용될 수도 있으나, 정보가 비동기 수집되지는 않습니다.
수집이 완료될 때까지 LoadModule()
호출은 블록됩니다.
코드가 에셋을 비동기식으로 발견하기를 기다리면서 Slate UI 프론트엔드가 있는 경우,
진행상황을 사용자에게 알리는 SAssetDiscoveryIndicator
위젯이 들어있을 것입니다.