https://dev.epicgames.com/documentation/ko-kr/unreal-engine/data-assets-in-unreal-engine

 

언리얼 엔진의 데이터 에셋 | 언리얼 엔진 5.4 문서 | Epic Developer Community

언리얼 엔진의 데이터 에셋에 대한 정보입니다.

dev.epicgames.com

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

 

언리얼 엔진에서 에셋 관리 | 언리얼 엔진 5.4 문서 | Epic Developer Community

에셋 로드 및 언로드

dev.epicgames.com

 

Data Asset

  • UDataAsset을 상속받은 Class들
  • 다양한 System 관련 정보들을 저장할 수 있다.
  • Game의 핵심 매커니즘이 아닌 비교적 덜 중요한 요소들에 주로 사용한다.

Primary Data Asset

  • UPrimaryDataAsset을 상속받은 Class들
    • Asset Manager는 GetPrimaryAssetId 함수를 통해 확보한 ID에서 Primary Asset을 직접 조작할 수 있다.
    • 반대로 Data Asset을 Primary Data Asset으로 만드려면 GetPrimaryAssetId 함수를 override하여
      유효한 FPrimaryAssetId 를 반환해야 한다.
  • FPrimaryAssetId는 다음 두 가지 요소로 구성되어 있다.
    • Primary Asset Type
      • Asset 그룹을 알려준다
    • Primary Asset Name
      • Contents Browser에서 노출되는 애셋 이름을 기본값으로 사용한다.
  • Asset Manager가 직접적으로 처리하고 Load 가능한 Asset들이 포함된다.
    • 대표적으로 UWorld
  • GetPrimaryAssetId 함수를 구현해 Asset Bundle을 지원하는 Asset Manager에서 수동으로 Load/Unload 할 수 있다.
    • 사용 시 Project Setting -> Asset Manager 탭에서 참조하고자 하는 Primary Asset의 Directory를 설정해야 한다.
    • 이 때, PrimaryAssetType에 작성한 Text가 GetPrimaryAssetId()에서 반환하는 값과 같아야 한다.

Secondary Data Asset

  • 공식적으로 지칭된 것은 아님
    • Asset Manager가 직접 처리하고 Load하지 못하고, Primary Asset에 의존적으로 처리되는 DataAsset을 지칭
  • 보통 대부분의 Asset들은 UWorld가 Load 될 때 같이 Load 되는 Secondary Asset이라 직접 Load 할 필요가 없다.

Asset Manager

  • Primary Asset의 Search 및 Load Process를 관리하는 Singleton
  • Asset Manager는 2가지 Type의 Asset을 처리한다.
    • Blueprint Class
    • BP 이외의 Asset
      • Level
      • UDataAsset Instance
  • Primary Asset Type에는 특정 BaseClass가 연결되며, 환경설정에서 Blueprint Class를 저장할지 여부가 지정된다.

Bueprint Class

  • Primary Asset의 Base Class가 될 수 있는 요소
    • Primary Data Asset
    • Primary Data Asset의 자손
    • GetPrimaryAssetId를 오버라이드 하는 Actor Subclass
  • 새로운 Blueprint Primary Asset을 생성하려면 위 요소를 Base로 하는 Blueprint Class를 생성하면 된다.
  • C++에서 Blueprint Primary Asset에 Access 하는 방법
    • GetPrimaryAssetObjectClass 함수 호출
    • 이름에 'Class'가 포함된 Blueprint Asset Manager 함수 호출
  • Blueprint Primary Asset Class를 확보하면 다른 Blueprint Class처럼 취급할 수 있다.
    • 새 Instance Spawn
    • GetDefaults 함수를 사용해 Blueprint와 연결된 Class Default Object의 ReadOnly Data에 Access
  • Blueprint Class를 Instance화 할 필요가 없는 경우 다음 두가지가 가능해진다.
    • UPrimaryDataAsset을 상속받은 Data-Only Blueprint에 Data 저장
    • Base Class에서 Child Class를 도출
      • UPrimaryDataAsset을 확장하는 UMyShape 클래스를 생성
      • UMyShape를 상속 받아 BP_MyRectangle라는 BP Class를 생성
      • MP_MyRectangle을 상속 받은 BP_MySquare BP Class 생성
      • 이 때 BP_MySquare의 PrimaryAssetId는 MyShape:BP_MySquare가 된다.

Blueprint 이외의 Asset

  • Primary Asset Type이 Blueprint Data를 저장할 필요가 없는 경우에 사용
  • Blueprint 이외의 Asset은 Code Access 측면에서 더 간편하고, 메모리 효율도 더 우수하다.
  • Editor에서 생성하는 방법
    • Advanced Contents Browser에서 New Data Asset을 생성
    • 혹은 Custom UI를 사용하여 새 New Level을 생성
  • Asset이 생성되는 원리는 Blueprint Class가 생성되는 원리와 다르다.
    • 생성한 Asset은 Class 그 자체가 아니라 Instance이다.
    • 때문에 Class나 다른 Asset을 상속 받을 수 없다.
  • Asset의 Class에 Access하는 방법
    • GetPrimaryAssetObject와 같은 C++ 함수 사용
    • 이름에 'Class'가 포함되지 않은 Blueprint 함수 사용
  • Class가 Load되면 직접 Access하여 Data를 읽을 수 있다.

StreamableManager

  • Primary Asset에 포함된 구조체
    • Object를 Async Load하는 작업 수행
    • Object를 Unload 할 수 있을 때까지 Streamable Handle을 이용해 Memory를 보존
  • Singleton인 Asset Manager와 달리 다양한 부분에서 서로 다른 용도의 Streamable Manager가 존재 함.

Asset Bundle

  • Primary Asset과 관련된 특정 Asset의 이름이 지정된 목록
  • 생성하는 방법
    • Meta Tag가 'AssetBundles'인 UObject의 TSoftObjectPtr이나
      FStringAssetReference 멤버로 구성된 UPROPERTY Section 에 Tag 지정
      • Tag 값은 Secondary Asset을 저장할 Bundle 이름을 나타낸다.
      • 더보기
        	/** 메시 */
        	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = Display, AssetRegistrySearchable, meta = (AssetBundles = "TestBundle"))
        	TSoftObjectPtr<UStaticMesh> MeshPtr;
        • 예를 들어,
          위 MeshPtr에 저장된 Static Mesh Asset은 UObject를 저장했을 때 TestBundle에 추가가 된다.
  • Runtime 시점에 Project의 Asset Manager Class로 등록
    • 이 경우 Programmer가 FAssetBundleData을 채워 Asset Manager에 전달하는 코드를 작성해야 한다.
    • 그 목적으로 Programmer는 아래 행동을 할 수 있다.
      • UpdateAssetBundleData 함수 override
      • Bundle의 Secondary Asset과 연결하려는 Primary Asset ID로 AddDynamicAsset 호출

Disk에 저장된 Primary Asset Regist 및 Load

  • 대부분의 Primary Asset은 Contents Browser에 표시되고, Disk에 저장된 Asset 파일로 존재한다.
    • 때문에 Artist나 Designer가 편집할 수 있다.
  • Programmer가 이런 용도의 Class를 생성하는 가장 간단한 방법은 UPrimaryDataAsset을 상속받는 것이다.
    • 이 Class에는 Asset Bundle Data를 Load/Save 하는 기능이 내장되어 있다.
    • 이 함수는 Asset Bundle을 사용하기 위해 필요한 기능을 구현한 가장 간단한 예시이기에
      다른 Base Class를 사용하려는 경우에 살펴보아도 좋다.
  • 더보기
    	/** 맵 화면에서 사용자가 선택할 수 있는 존 */
    	UCLASS(Blueprintable)
    	class MYGAME_API UMyGameZoneTheme : public UPrimaryDataAsset
    	{
    		GENERATED_BODY()
     
    		/** 존 이름 */
    		UPROPERTY(EditDefaultsOnly, Category=Zone)
    		FText ZoneName;
     
    		/** 이 존에 진입할 때 로드될 레벨 */
    		UPROPERTY(EditDefaultsOnly, Category=Zone)
    		TSoftObjectPtr<UWorld> LevelToLoad;
     
    		/** 맵에 이 존을 표현하는 데 사용되는 블루프린트 클래스 */
    		UPROPERTY(EditDefaultsOnly, Category=Visual, meta=(AssetBundles = "Menu"))
    		TSoftClassPtr<class AGameMapTile> MapTileClass;
    	};
    • 위 Class는 Virtual 환경에서 Zone Type을 지정하는 방법을 알 수 있는 예시코드다.
    • Zone Type은 Game 전체 Map 화면에 World를 시각적으로 표현할 때 사용할 Art Asset을 Game에 알려준다.
    • UMyGamezoneTheme은 UprimaryDataAsset을 상속 받았다.
      • 따라서 Asset의 약식 이름과 NativeClass를 사용하는 유효한 버전의 GetPrimaryAssetId가 존재한다.
      • 예를 들어, Forest라는 이름으로 저장된 UMyGameZoneTheme의 Primary Asset Id는 'MyGameZoneTheme:Forest'이다.
    • Editor에서 UMyGameZoneTheme Asset을 저장할 때마다 PrimaryDataAsset::AssetBundleData가
      업데이트 되어 해당 Asset을 Secondary Asset에 추가한다.
  • Primary Asset을 Regist/Load 하려면 다음 액션을 수행해야 한다.
    1. Project의 Custom Asset Manager Class를 Engine에 알린다.
      • DefaultEngine.ini 파일에서 [/Script/Engine.Engine] Section의 AssetManagerClassName 변수를 설정한다.
      •  [/Script/Engine.Engine]
         AssetManagerClassName=/Script/Module.UClassName

        • 여기서 Module은 Project의 Module Name을 뜻한다.
        • UClassName은 사용하려는 UClass의 이름을 뜻한다.
      • 단, Project에 특수 기능이 필요하지 않는 경우에는 이 단계를 건너뛴다.
    2. Primary Asset을 AssetManager에 Regist한다.
      • Project Settings 메뉴에서 구성
        • Primary Asset Types to Scan 검색/등록 할 Primary Asset의 Type, 위치 및 용도 나열
          Directories to Exclude Primary Asset Scan 대상에서 명시적으로 제외되는 Directory
          Test Asset을 제외하는데 유용
          Primary Asset Rules Asset 처리 방법이 명시된 구체적인 Override 나열
          Only Cook Production Assets DevelopmentCook으로 지정된 Asset이 Cooking 과정에서 오류를 유발하도록 설정
          최종 배포 빌드에서 Test Asset 제거에 유용
          Primary Asset ID Redirects 이 목록에 ID가 표시되는 Primary Asset 관련 Data를 조회할 때 제공되는 대체 ID로 교체
          Primary Asset Type Redirects Primary Asset 관련 Data를 조회할 때 원래 Type 대신 이 목록에서 제공되는 Type으로 교체
          Primary Asset Name Redirects Primary Asset 관련 Data 조회 할 때 제공되는 Asset Name으로 교체
      • 시작 시점에서 Primary Asset을 Asset Manager Class에 등록하도록 Programming
        • AssetManager::StartInitialLoading 함수 override
        • 해당 함수에서 ScanPathsForPrimaryAssets 호출
        • 이 방식의 경우, 동일한 Type의 Primary Asset은 하나의 Sub Folder에 넣는 것이 좋다
          • Search/Register 속도가 빨라진다.
    3. Asset을 Load한다. 
      • AssetManager 함수를 사용해 적시에 Primary Asset를 Load/Unload 할 수 있다.
        • LoadPrimaryAssets / UnloadPrimaryAssets
        • LoadPrimaryAsset / UnloadPrimaryAsset
        • LoadPrimaryAssetsWithType / UnloadPrimaryAssetsWithType
      • 이 방식을 사용하면 Asset Manager가 해당 Asset Bundle을 참조해 Secondary Asset을 Load 한다.

Runtime 상에 생성된 Primary Asset Regist/Load

  • Runtime 상에서 Primary Asset을 Regist/Load 하는 이유를 이해하는데 유용한 함수가 있다.

ExtractSoftObjectPaths

  • UScriptStruct의 모든 UPROPERTY를 검사하고, Asset Reference를 식별한 뒤 Asset Name Array에 저장
    • Asset Name Array는 Asset Bundle을 만들 때 사용할 수 있다.
    • 더보기
      virtual void ExtractSoftObjectPaths
      (
          const UStruct * Struct,		// Asset Reference를 검색 할 UStruct
          const void * StructValue,		// Struct를 가르키는 void pointer
          TArray< FSoftObjectPath > & FoundAssetReferences,		// Struct에서 찾은 Asset Reference를 반환
          const TArray< FName > & PropertiesToSkip		// FoundAssetReferences에서 제외할 Property Name Array
      ) const

RecursivelyExpandBundleData

  • Primary Asset과 관련된 모든 Reference를 찾고, 재귀적 확장을 통해 Asset Bundle의 모든 Dependency를 탐색.
    • 더보기
      virtual void RecursivelyExpandBundleData
      (
      	/*
          * Asset Reference가 포함되어 있는 Bundle Data
          * 재귀적으로 확장되며, 연관된 Assset Set을 Load하는데 유용하다.
          */
          FAssetBundleData & BundleData
      ) const

       

      	// theater ID에서 추출한 이름 구성
      	UMyGameAssetManager& AssetManager = UMyGameAssetManager::Get();
      	FPrimaryAssetId WorldMapAssetId = FPrimaryAssetId(UMyGameAssetManager::WorldMapInfoType, FName(*WorldMapData.UniqueId));
       
      	TArray<FSoftObjectPath> AssetReferences;
      	AssetManager.ExtractSoftObjectPaths(FMyGameWorldMapData::StaticStruct(), &WorldMapData, AssetReferences);
       
      	FAssetBundleData GameDataBundles;
      	GameDataBundles.AddBundleAssets(UMyGameAssetManager::LoadStateMenu, AssetReferences);
       
      	// 재귀적 레퍼런스 확장을 통해 존에서 타일 블루프린트 픽업
      	AssetManager.RecursivelyExpandBundleData(GameDataBundles);
       
      	// 다이내믹 에셋 등록 
      	AssetManager.AddDynamicAsset(WorldMapAssetId, FSoftObjectPath(), GameDataBundles);
       
      	// 프리로드 시작
      	AssetManager.LoadPrimaryAsset(WorldMapAssetId, AssetManager.GetDefaultBundleState());

'UE5 > Architecture' 카테고리의 다른 글

[Architecture] String  (0) 2024.05.06
[Architecture] Asset Registry  (1) 2024.05.06
[Architecture] Asset Reference  (0) 2024.05.06
[Architecture] Module(+ Package)  (0) 2024.05.03
[Architecture] Async Asset Loading  (0) 2024.05.03

+ Recent posts