TECHARTNOMAD | TECHARTFLOWIO.COM

TECH.ART.FLOW.IO

[번역] UE5 Virtual Assets 가용성 분석

jplee 2025. 10. 12. 23:34

역자의 말: 텐센트에서 근무하는 엔지니어 lipengzha의 예전 포스트를 번역해 봤습니다.  언리얼 엔진 5 의 가상 자산 시스템에 대한 내용이 일목요연하게 정리되어 있습니다.

Personal Insight : 스타트업에서도 언리얼엔진으로 프로젝트를 진행 한다면 P4를 VCS 로 사용하는것이 좋다고 생각합니다. 비용이 들어간다고 무료인 SVN 을 사용해서 누적 된 시간적 소비를 ROI 분석적으로 접근 하면 P4 를 사용하는 것이 년단위로 이득입니다. 대기업이 마냥 돈이 넘처흘러서 P4를 사용하는것이 아니라는 걸 알아야 합니다. 언리얼 엔진 프로젝트에는 아직까지는 P4가 여러 방면에서 VCS 로 최선입니다. 

게임 규모와 에셋 정밀도가 향상되고 Nanite와 같은 기술이 적용됨에 따라 프로젝트 엔지니어링 규모가 수백 GB에서 심지어 TB 단위로 급격히 증가하며, 전체를 다운로드하는 데 몇 시간이 걸릴 수 있습니다.

실제 개발에서 각 개인이 사용할 수 있는 리소스는 그 중 일부에 불과하므로, 프로젝트 다운로드 규모를 줄이고 프로젝트를 경량화하는 방법은 최적화가 필요한 문제입니다.

UE5에서는 공식적으로 Virtual Assets 메커니즘을 도입했으며, P4와 결합하여 이를 달성할 수 있습니다.

이 글에서는 UE5의 가상 에셋 구성 프로세스, 에셋의 가상화 과정과 로딩 코드 분석, 그리고 네트워크 연결이 끊긴 상태에서의 가용성 테스트에 대해 소개합니다.

참고: Virtual Assets는 P4 버전 관리와만 결합할 수 있으며, Git 및 SVN은 지원하지 않습니다.

서론

Virtual Assets는 에셋 메타 정보와 데이터를 분리하는 솔루션으로, 기존 UE 프로젝트의 uasset을 uasset+payload 형태로 분할할 수 있습니다. 로드할 필요가 없는 에셋의 경우 가상화된 uasset만 있으면 되며, 실제 에셋 BulkData는 포함되지 않습니다. 해당 에셋에 실제로 액세스할 때 서버에서 에셋의 Payload 데이터를 다운로드하여 프로젝트 다운로드 규모를 줄이는 목적을 달성합니다.

[Payload](https://en.wikipedia.org/wiki/Payload_(computing)란?

Payload는 에셋의 실제 데이터 부분을 의미합니다. 예를 들어:

  • 텍스처(Texture): 실제 이미지 픽셀 데이터
  • 스태틱 메시(Static Mesh): 버텍스, 인덱스, UV 등의 지오메트리 데이터
  • 사운드(Sound): 오디오 웨이브폼 데이터

가상화 과정에서 이러한 Payload 데이터는 원본 .uasset 파일에서 분리되어 별도의 .upayload 파일로 저장됩니다. 가상화된 .uasset 파일은 에셋의 메타데이터(속성, 참조 정보 등)만 포함하고 있어 크기가 매우 작습니다(수 MB에서 수십 KB로 축소). 실제 에셋을 열거나 사용할 때만 서버에서 해당 Payload를 다운로드하여 로드하게 됩니다.

Epic 자체 데이터에서도 가상화 데이터가 매우 우수합니다 (Texture가 대부분을 차지하며, 텍스처만 가상화해도 전체 크기의 60%를 줄일 수 있음):

가상화 활성화

공식 문서 소개에 따르면 VirtualAssets는 기본적으로 비활성화 상태이며, 다음 구성 파일을 추가하여 수동으로 활성화해야 합니다:

[Core.ContentVirtualization]
SystemName=Default

[Core.VirtualizationModule]
BackendGraph=VABackendGraph_Example

[VABackendGraph_Example]
PersistentStorageHierarchy=(Entry=SourceControlCache)
CacheStorageHierarchy=(Entry=DDCCache)
SourceControlCache=(Type=p4SourceControl, DepotRoot="...")
DDCCache=(Type=DDCBackend)

DepotRoot는 가상화 파일의 저장 경로를 지정해야 합니다. 예를 들어 //remote_depot/branches/Project/Content/VirtualAssets/에 저장하며, Content 디렉토리 아래에 배치할 필요는 없고 해당 디렉토리를 다운로드할 필요도 없습니다.

가상화 / 제출 프로세스

앞의 구성을 완료한 후 엔진에 들어가서 P4에 연결하면 에셋을 가상화할 수 있습니다. 엔진은 CheckIn 시 자동으로 가상화 프로세스를 실행하는 것을 지원합니다.

엔진 내에서 p4에 연결:

에셋을 check-in하면 자동으로 에셋 가상화가 실행되고 P4에 제출됩니다:

제출 후 p4에서 제출 기록과 각 해시와 에셋의 대응 관계를 확인할 수 있습니다:

Description의 내용: 앞의 6자는 경로(2자마다 한 단계 경로), 뒤의 부분은 실제 해시 값입니다.

엔진에서 Has Virtualized Data를 확인하여 에셋이 가상화되었는지 확인할 수 있습니다:

p4에서 설정한 Depot 디렉토리 아래에 upayload 파일이 추가됩니다:

upayload 파일의 저장 방식은 해시로 명명되며, 타입이나 경로별로 구분되지 않습니다.

예를 들어, Texture와 StaticMesh의 payload는 경로와 이름만으로는 전혀 구별할 수 없습니다:

가상화 후 Asset의 크기가 눈에 띄게 변경됩니다(몇 MB에서 10KB 수준으로):

Editor 내 CheckIn 외에도 엔진은 UnrealVirtualizationTool 도구를 제공하여 일괄 가상화 및 역변환을 수행할 수 있습니다.

실행 매개변수:

Usage:
	Commands:
		<ProjectFilePath> -Mode=Virtualize -Changelist=<number> -Submit [optional]
		<ProjectFilePath> -Mode=Virtualize -Path=<string>
		LogVirtualizationTool: Display:
		<ProjectFilePath> -Mode=Rehydrate -Package=<string>
		<ProjectFilePath> -Mode=Rehydrate -PackageDir=<string>
		<ProjectFilePath> -Mode=Rehydrate -Changelist=<number>
	Legacy Commands:
		-Mode=Changelist -ClientSpecName=<name> [optional] -Changelist=<number> -nosubmit [optional]
		-Mode=PackageList -Path=<string>
	Global Options:
	        -MinimalLogging (demote log messages with 'display' verbosity to 'log' verbosity except those using the LogVirtualizationTool category)

일부 에셋만 가상화

에셋 타입 비활성화

특정 타입이 가상화에 참여하지 않도록 하려면 엔진에서 구성 지원을 제공합니다.

DefaultEngine.ini에서 특정 타입의 에셋이 가상화에 참여하지 않도록 제어:

Developer/Virtualization/Private/VirtualizationManager.cpp

TArray<FString> DisabledAssetTypesFromIni;
if (ConfigFile.GetArray(LegacyConfigSection,TEXT("DisabledAsset"), DisabledAssetTypesFromIni) >0 ||
	ConfigFile.GetArray(ConfigSection,TEXT("DisabledAsset"), DisabledAssetTypesFromIni) >0)
{
UE_LOG(LogVirtualization, Display,TEXT("\\tVirtualization is disabled for payloads of the following assets:"));
	DisabledAssetTypes.Reserve(DisabledAssetTypesFromIni.Num());
for(const FString& AssetType : DisabledAssetTypesFromIni)
	{
UE_LOG(LogVirtualization, Display,TEXT("\\t\\t%s"), *AssetType);
		DisabledAssetTypes.Add(FName(AssetType));
	}
}

Core.ContentVirtualization 또는 Core.VirtualizationModule 섹션 아래에 추가할 수 있습니다:

[Core.VirtualizationModule]
+DisabledAsset="Texture2D"

시작 시 다음과 같은 출력이 표시됩니다:

LogVirtualization: Display: 	Virtualization is disabled for payloads of the following assets:
LogVirtualization: Display: 		Texture2D

엔진 내에서 텍스처를 제출할 때 자동으로 가상화되지 않습니다.

하지만 엔진은 현재(UE5.6.0) DiabledAsset 구성만 제공하며, 이는 블랙리스트에 해당합니다. 화이트리스트와 유사한 옵션은 제공하지 않으며, 엔진 코드를 직접 수정하여 확장할 수 있습니다.

경로 / 에셋 비활성화

특정 경로/에셋의 가상화 여부를 제어하려면 다음 구성을 DefaultEngine.ini에 추가할 수 있습니다:

DefaultEngine.ini

[/Script/Virtualization.VirtualizationFilterSettings]
+ExcludePackagePaths="/Game/Meshs"
+IncludePackagePaths="/Game/Textures"

이 두 구성은 FVirtualizationManager::ShouldVirtualizePackage에서 사용됩니다:

주의 사항

  1. Saved/VASubmission 디렉토리를 p4ignore로 표시할 수 없으며, 추가하면 필터링됩니다.
  2. 에셋을 가상화한 후 엔진 내에서 에셋을 삭제하더라도 해당 가상화 파일은 삭제되지 않고 계속 누적됩니다.
  3. 가상화 파일은 자동으로 중복 제거되므로, 예를 들어 동일한 이미지를 반복해서 가져와도 여러 개의 upayload가 생성되지 않고 하나를 공유합니다.
  4. 네트워크에 연결할 수 없거나 속도가 느린 경우 Payload 추출이 느려져 VA의 효율성에 영향을 줍니다.
  5. UnrealVirtualizationTool을 통해 일괄 가상화 및 역변환을 수행할 수 있습니다.

가상화 데이터 로딩

DDC에서 가져오기

이미 가상화된 에셋을 로드할 때 먼저 DDC(Derived Data Cache)에서 가져옵니다:

UE5에서 로컬 DDC의 경로는 %LOCALAPPDATA%/UnrealEngine/Common/Zen/Data이며, 로컬에 DDC 캐시가 없는 상황을 시뮬레이션하려면 해당 디렉토리를 삭제할 수 있습니다.

DDC에서 가져올 수 있으면 P4의 payload를 요청하지 않습니다.

p4에서 가져오기

DDC에서 에셋 캐시를 가져올 수 없으면 P4에서 가져오려고 시도합니다:

데이터를 가져온 후에는 일반 에셋 액세스와 차이가 없습니다.

네트워크 액세스 없음

에셋 가상화를 활성화했고 DDC에 캐시가 없는 경우, 네트워크 장애로 P4에 액세스할 수 없으면 리소스를 열 때 다음과 같은 오류가 발생합니다:

요청을 재시도하거나 엔진을 종료해야 합니다.

수동으로 로드되는 에셋도 이 논리를 따릅니다(예: 씬 열기 -> 모델 로드 -> 텍스처 로드). 텍스처의 가상화 데이터를 로드할 수 없으면 맵도 열 수 없습니다:

즉, 네트워크 상태가 좋지 않으면 Virtual Assets가 완전히 사용할 수 없는 상태가 됩니다.

엔진 내에서 Core.VirtualizationModule에서 UseLegacyErrorHandling을 통해 팝업을 무시하고 편집기를 종료하지 않을 수 있지만, assertion이 트리거됩니다. 텍스처는 치명적이지 않은 assertion이고 StaticMesh는 치명적인 assertion입니다.

텍스처를 열 때 오류가 발생하지 않도록 할 수 있지만 텍스처 크기는 0x0으로 표시됩니다:

참고: 네트워크 없음 문제에 대해 필자는 UDN에서 Epic 공식에 문의했으며, 현재 공식적으로 네트워크 연결이 끊긴 상태에서 임시 데이터를 fallback하는 개발 계획은 없으며, 대신 네트워크가 양호할 때 전체 payload 데이터를 다운로드할 것을 권장합니다.

오류 처리

p4 server 구성

엔진 내에서 check-in 시 다음과 같은 오류가 발생하는 경우:

SourceControl: Error: CommandMessage Command: CreateWorkspace, Error: Error in client specification.
'partitioned' client type has not been configured for this server.
Storage location 'client.readonly.dir' needs to be set by the administrator.

Virtual Assets도 p4 server에서 구성 지원이 필요하기 때문이며, 다음 두 가지 구성을 활성화해야 합니다:

  • partitioned
  • 가상화 저장 디렉토리(DepotRoot)를 client.readonly.dir로 설정

그러면 check-in 시 가상화하고 제출할 수 있습니다:

관련 자료

공식 문서

총평

전반적으로 UE5의 Virtual Assets는 에셋 다운로드 양을 크게 줄일 수 있는 리소스 관리 방식이며, 네트워크가 원활한 상황에서 에셋 액세스 경험은 네이티브와 크게 다르지 않습니다.

Virtual Assets는 Shared DDC와 결합하는 것이 가장 좋습니다. 두 가지가 강력하게 연관되어 있지는 않지만, 사용 경험 측면에서는 여전히 필요합니다. 해당 에셋이 DDC에 한 번 캐시되면 모든 사용자가 P4 Server에서 파일을 다운로드하지 않고 DDC에서 우선적으로 액세스하므로 p4 Server의 다운로드 부담을 크게 완화할 수 있습니다.

또한 가상화는 에셋 중복 제거 효과도 가져올 수 있습니다. 예를 들어 동일한 텍스처가 두 번 반복해서 가져와진 경우 실제로는 하나의 Payload만 있어 에셋 저장소 중복을 방지할 수 있습니다(그러나 실제 에셋의 uasset은 여전히 두 개이지만 크기가 작음).

또한 Virtual Asset은 P4와만 결합할 수 있으며, 다른 버전 관리 시스템에 대한 지원이 충분하지 않고, 네트워크 연결이 끊긴 상태에서는 사용할 수 없으므로 프로젝트의 실제 상황에 따라 활성화 여부를 평가해야 합니다.

제 권장 사항: UE5 신규 프로젝트에서 P4를 버전 관리로 사용하고, 내부 네트워크 안정성이 양호하며 SharedDDC를 배포할 수 있는 경우 가상 에셋을 활성화할 수 있습니다.