DDC 는 파생 데이터 캐시(Derived Data Cache) 를 의미합니다.
많은 언리얼 엔진 에셋은 추가적인 '파생 데이터'가 있어야만 사용할 수 있습니다. 간단한 예로 셰이더가 있는 머티리얼을 들 수 있습니다. 머티리얼을 렌더링하려면 먼저 셰이더를 에디터가 실행 중인 플랫폼용으로 컴파일해야 합니다.
파생 데이터는 크고 재생성이 필요할 때도 있으므로 소스 컨트롤에 체크인하지 않습니다. 대신 파생 데이터 캐시(DDC)에 보관됩니다.
DDC 저장 위치
프로젝트와 시스템 환경설정 방식에 따라 빠른 캐시부터 느린 캐시까지 계층구조에 여러 DDC 캐시가 있을 수 있습니다. 파생 데이터를 평가할 때, 시스템은 다음을 수행하여 파생 데이터 액세스 속도를 결정합니다.
- 파생 데이터 조각이 필요한 경우, 가장 빠른 캐시 순으로 캐시를 확인하며 데이터를 찾습니다.
- 데이터를 찾으면 다음에는 더 빨리 액세스할 수 있도록 가장 빠른 로컬 캐시에 데이터가 복사합니다.
- 데이터를 찾지 못하면, 데이터를 처음 생성한 다음 향후에 사용자와 사용자의 팀이 이용할 수 있도록 캐시에 비동기식으로 복사합니다.
DDC에 저장된 콘텐츠는 일회용으로, .uasset 파일에 저장된 데이터를 사용하여 언제든 재생성할 수 있습니다. 이러한 파생 포맷을 외부에 저장하면 소스 에셋 파일을 수정할 필요 없이 엔진에서 해당 포맷을 쉽게 추가하거나 변경할 수 있습니다.
DDC 타입
일반적으로 최소한 다음과 같은 두 개의 캐시가 있습니다.
- 부트 DDC(Boot DDC): 부팅 속도 향상을 위해 메모리에 로드되는 스타트업 파일입니다.
- 예시: ProjectDir/DerivedDataCache/Boot.ddc
- 로컬 DDC(Local DDC): 프로젝트에 대한 파생 데이터입니다.
- 예시: EngineDir/DerivedDataCache
하지만, DDC Pak 또는 공유 DDC(Shared DDC) 를 사용하도록 프로젝트를 구성할 수도 있습니다.
DDC Pak
에픽게임즈 스토어에서 언리얼 엔진을 다운로드하면 엔진에 DDC Pak(.ddp)이 포함되어 있습니다. DDC Pak에는 모든 엔진 콘텐츠에 대한 파생 데이터가 포함되어 있으므로 셰이더 등을 컴파일하지 않고도 작업을 시작할 수 있습니다. 마찬가지로, 일부 샘플이 같은 이유로 DDC Pak과 함께 제공됩니다.
- 엔진 DDC Pak
- 예시: EngineDir/DerivedDataCache/Compressed.ddp
- 프로젝트 DDC Pak
- 예시: ProjectDir/DerivedDataCache/Compressed.ddp
공유 DDC
같은 위치에 있는 팀이라면 공유 DDC를 설정하는 것을 적극 권장합니다. 공유 DDC는 모든 팀원과 빌드 머신이 읽고 쓸 수 있는 네트워크 드라이브입니다. 공유 DDC를 설정하면 팀 전체에 걸쳐 필요한 DDC 데이터 생성 비용이 감소합니다. 예를 들어, 아티스트가 셰이더를 편집하면 DDC 데이터가 공유 DDC에 바로 작성됩니다.
- 공유 DDC: 네트워크 드라이브나 매핑된 드라이브가 됩니다.
공유 드라이브의 예: \epicgames.net\root\DDC-Global-Fortnite
공유 DDC 사용하기
스튜디오에서는 특정 위치의 모든 사용자가 액세스할 수 있는 공유 DDC를 사용해야 합니다. 공유 DDC를 사용하면 한 사람만 파생 에셋 포맷을 빌드해도 다른 모든 사용자가 자동으로 사용할 수 있게 됩니다. 에셋을 처리해야 할 때 가끔 지연이 발생하기도 하지만, 그 결과는 저장되고 공유됩니다. 매우 소규모의 팀이라도 이 방식으로 에셋 처리 작업을 공유하면 대부분의 처리 시간이 단축됩니다.
인터넷을 통해 전체 DDC를 복사하거나 DDC를 백업하거나 백업한 DDC를 복원하는 것은 권장하지 않습니다. 반드시 해롭다고는 할 수 없지만, 로컬에서 처음부터 생성하는 것보다 DDC에 저장된 데이터양을 전송하는 데 시간이 오래 걸리므로 시간 낭비일 수 있습니다. 프로젝트가 대규모이고 사전 빌드된 DDC 데이터를 배포하려는 경우에는 DDC Pak을 생성해야 합니다.
공유 DDC 구성하기
BaseEngine.ini
에서 볼 수 있듯, 에디터는 이미 세 가지 방법 중 하나를 활성화할 수 있는 공유 DDC를 사용하도록 구성되어 있습니다.
아래에 가장 권장되는 방법 순으로 이러한 옵션이 나와 있습니다.
-
아래 그림과 같이 프로젝트의 DefaultEngine.ini에 팀의 유효 위치에 대한 경로를 설정하는 오버라이드를 추가합니다.
[DerivedDataBackendGraph] Shared=(Type=FileSystem, ReadOnly=false, Clean=false, Flush=false, DeleteUnused=true, UnusedFileAge=10, FoldersToClean=10, MaxFileChecksPerSec=1, ConsiderSlowAt=70, PromptIfMissing=false, Path=\\YourCompanyServer\DDC, EnvPathOverride=UE-SharedDataCachePath, EditorOverrideSetting=SharedDerivedDataCache)
-
아래 그림과 같이 사용할 폴더로
UE-SharedDataCachePath
환경 변수(Mac/Linux의 경우UE_SharedDataCachePath
)를 설정합니다. -
에디터에서
SharedDerivedDataCache
변수를 설정합니다.
전체 크기로 보려면 이미지를 클릭하세요.
\YourCompanyServer\DDC 에 특별한 작업을 하지 않아도 되며, 쓰기가 가능하다면 엔진이 필요한 구조를 생성합니다.
공유 DDC 비활성화하기
공유 DDC가 환경설정된 프로젝트에서 원격으로 작업하는 개발자는 DDC 데이터를 생성하는 것보다 액세스하는 데 시간이 더 오래 걸리기 때문에 퍼포먼스 저하를 겪을 수 있습니다. 임시로 공유 DCC을 비활성화하려면 아래 방법 중 하나를 사용하면 됩니다.
- 명령줄에서 -ddc=noshared를 전달합니다.
- 환경 변수를 로컬 하드 드라이브로 설정합니다.
UE-SharedDataCachePath=None
- Mac의 경우:
UE_SharedDataCachePath=None
파생 데이터 빌드하기
에셋을 임포트하는 사용자는 엔진에서 그 에셋을 사용하고 테스트할 것이므로 파생 데이터를 빌드하는 사용자입니다. 하지만, 새 에셋을 처리해야 하는 경우가 있을 수 있습니다. 이러한 에셋 처리는 필요에 따라 자동으로 수행되며, 가끔 지연이 발생할 수는 있지만 빠른 하드웨어에서 실행할 때는 큰 영향을 미치지 않습니다.
언제든지 언리얼 엔진 설치 폴더에서 다음 명령을 실행하여 DDC를 채울 수 있습니다.
Engine\Binaries\Win64\UnrealEditor.exe ProjectName -run=DerivedDataCache -fill
에픽게임즈는 매일 밤 이 작업을 수행하여 DDC가 항상 준비되어 있도록 하지만, 일반 자동 캐싱 기능만으로도 충분하므로 이 작업이 꼭 필요한 것은 아닙니다.
DDC 폴더 마운트하기
내부 네트워크를 통해 DDC를 사용하려면, 해당 DDC가 포함된 폴더를 네트워크 드라이브에 마운트해야 합니다. 폴더 마운트 방법이 익숙하지 않다면 Windows에서 네트워크 드라이브 매핑을 참조하세요.
DDC로 배포하기
쿠킹된 빌드는 DDC를 사용하거나 필요로 하지 않기 때문에 게임 패키징 메서드로 쿠킹이 선호됩니다. 그렇지만, 필요한 경우에는 배포용으로 DDC를 패키지로 만들 수 있습니다.
DDC 패키징 방법
-
엔진의 Engine/Binaries/Win64 디렉터리에서 UnrealEditor.exe를 실행하여 아래의 실행인자를 전달합니다.
UnrealEditor.exe ProjectName -run=DerivedDataCache -fill -DDC=CreatePak
- 이렇게 하면 Project\DerivedDataCache 디렉터리에 DDC.ddp 파일이 생성됩니다.
- 엔진이 자동으로 .ddp 파일을 탐지하고 사용합니다.
DDC 세팅
DDC 세팅 보관 위치
DDC 세팅은 DefaultEngine.ini
파일의 [DerivedDataBackendGraph]
섹션 아래에 보관됩니다. BaseEngine.ini
에서 기본값을 확인할 수 있습니다.
[DerivedDataBackendGraph]
; 최소 7일 동안 파일을 보관합니다.
MinimumDaysToKeepFile=7
; 루트 항목을 환경설정합니다. KeyLength 노드를 사용하여 긴 스트링을 해싱한 다음 AsyncPut에 요청을 전달합니다.
Root=(Type=KeyLength, Length=120, Inner=AsyncPut)
; AsyncPut 항목을 환경설정합니다. AsyncPut 노드를 사용한 다음 Hierarchy에 요청을 전달합니다.
AsyncPut=(Type=AsyncPut, Inner=Hierarchy)
; 계층구조 항목을 환경설정합니다. 읽기가 발견될 때까지(쓰기는 모든 쓰기 가능 항목으로 이동) 순서대로 사용된 여러 노드를 사용합니다.
Hierarchy=(Type=Hierarchical, Inner=Boot, Inner=Pak, Inner=EnginePak, Inner=Local, Inner=Shared)
; 부트 노드를 환경설정합니다. 부팅 속도를 높이는 데 사용되는 데이터 512MB를 보유합니다.
Boot=(Type=Boot, Filename="%GAMEDIR%DerivedDataCache/Boot.ddc", MaxCacheSize=512)
; 로컬 노드를 환경설정합니다. 이는 다음과 같은 세트가 있는 파일 시스템 노드입니다.
; Readonly: 이 레이어에 데이터를 쓸 수 있습니다.
; Clean: 실행 시 오래된 파일을 클린업합니다.
; Flush: DDC를 폐기하고 다시 시작합니다.
; PurgeTransient: DDC에 휘발성 데이터를 보관하지 않습니다.
; DeleteUnused: 오래된 파일을 클린업합니다(백그라운드 스레드에서 진행).
; UnusedFileAge: 파일이 제거된 이후 연령입니다.
; FoldersToClean: 세션에서 정리할 최대 폴더 수입니다. -1 = 무제한
; MaxFileChecksPerSec: 초당 확인할 파일 수입니다.
; Path: 파일 시스템 DDC에 사용할 경로입니다.
; EnvPathOverride: 설정 시 경로 대신 사용되는 환경 변수입니다. 예시: UE-LocalDataCachePath=d:\DDC. ('없음(None)'이면 DDC 비활성화)
; CommandLineOverride: 디폴트 및 환경 변수 세팅보다 우선해서 사용되는 명령줄 실행인자입니다. 예시: -SharedDataCachePath=\\someshare\folder
; EditorOverrideSetting: 디폴트/환경 변수/명령줄 값을 오버라이드하는 에디터 사용자 세팅입니다.
Local=(Type=FileSystem, ReadOnly=false, Clean=false, Flush=false, PurgeTransient=true, DeleteUnused=true, UnusedFileAge=34, FoldersToClean=-1, Path=%ENGINEDIR%DerivedDataCache, EnvPathOverride=UE-LocalDataCachePath, EditorOverrideSetting=LocalDerivedDataCache)
; 로컬 이후에 액세스되는 공유 DDC를 환경설정합니다. 파일 시스템 DDC이며 파라미터는 위에서 설명한 것과 같습니다.
Shared=(Type=FileSystem, ReadOnly=false, Clean=false, Flush=false, DeleteUnused=true, UnusedFileAge=10, FoldersToClean=10, MaxFileChecksPerSec=1, Path=?EpicDDC, EnvPathOverride=UE-SharedDataCachePath, EditorOverrideSetting=SharedDerivedDataCache, CommandLineOverride=SharedDataCachePath)
; 로컬 이후에 액세스되는 대체 공유 DDC를 환경설정합니다. 파일 시스템 DDC이며 파라미터는 위에서 설명한 것과 같습니다.
AltShared=(Type=FileSystem, ReadOnly=true, Clean=false, Flush=false, DeleteUnused=true, UnusedFileAge=23, FoldersToClean=10, MaxFileChecksPerSec=1, Path=?EpicDDC2, EnvPathOverride=UE-SharedDataCachePath2)
; Project Pak 노드를 환경설정합니다. 런타임 가져오기 및 생성을 줄이기 위해 배포할 수 있는 사전 생성된 프로젝트용 DDC 데이터 파일입니다.
; DerivedDataCache 커맨드릿을 통해 DDP를 생성하는 방법에 대한 문서를 참조하세요.
Pak=(Type=ReadPak, Filename="%GAMEDIR%DerivedDataCache/DDC.ddp")
; Project Pak 노드를 환경설정합니다. 런타임 가져오기 및 생성을 줄이기 위해 배포할 수 있는 사전 생성된 엔진 DDC 데이터 파일입니다.
EnginePak=(Type=ReadPak, Filename=%ENGINEDIR%DerivedDataCache/DDC.ddp)
자주 묻는 질문
질문: 여러 개의 DDC 세팅을 보유할 수 있나요?
예! DefaultEngine.ini
파일에 새 [YourDDCSettings] 항목을 생성한 다음 -ddc=YourDDCSettings
를 사용하여 에디터를 실행하면 됩니다.
에픽에서는 세 가지 이유로 이를 지원합니다.
- 글로벌 DDC 대신 자체 DDC를 사용하려는 사무실 팀을 위해
- DDC Pak 생성 시
[CreateInstalledEnginePak]
같이 .pak 파일에 들어가는 내용을 제어하는 여러 옵션 중 하나를 사용하기 때문에 - 인터넷이 느리거나 VPN이 활성화되지 않아 공유 DDC를 사용하고 싶어 하지 않는 재택 근무자를 위해
BaseEngine.ini
파일에 위의 3번의 이유로 사용되는 NoShared(-ddc=NoShared
)를 포함하여 여러 DDC 항목이 기본적으로 포함된 것을 확인할 수 있습니다.
질문: 디스크 여유 공간이 부족합니다. 로컬 DDC를 다른 곳으로 이동할 수 있나요?
예! 프로젝트의 에디터 개인설정에서 조정할 수 있습니다. 또한, UE-LocalDataCachePath
환경 변수를 선택한 경로로 설정할 수도 있습니다. 예시: UE-LocalDataCachePath=d:\DDC
- 명령 프롬프트에서
"setx UE-LocalDataCachePath d:\DDC"
를 입력합니다. - 에픽 런처, UGS, Visual Studio 등 언리얼 엔진을 실행하는 모든 애플리케이션과 함께 언리얼 엔진을 재시작합니다.
기본 드라이브 공간이 부족할 때나 여러 브랜치에서 작업하고 있어 데이터 중복을 배제하고 싶은 경우에 이 방법을 사용할 수 있습니다.
질문: 네트워크 연결 속도가 느립니다. 공유 DDC를 끌 수 있나요?
예! 임시로 끌지 영구적으로 끌지에 따라 두 가지 옵션이 있습니다.
- DDC에 대한 환경 변수를
없음(None)
으로 설정하면 DDC가 비활성화됩니다. 이 경우UE-SharedDataCachePath=None
으로 설정합니다. -ddc=noshared
를 사용하여 에디터를 실행합니다.
질문: 공유 DDC 경로를 변경할 수 있나요?
예! 앞서 언급한 UE-SharedDataCachePath
를 설정하여 경로를 변경할 수 있습니다.
하지만, UE-SharedDataCachePath
를 로컬 경로로 설정하면 안 됩니다! 로컬 경로로 설정하면 사용하는 컴퓨터에 로컬 캐시와 공유 캐시가 모두 있게 되어 아무 이득 없이 디스크 공간만 두 배로 사용됩니다!
질문: DDC 문제는 어떻게 진단할 수 있나요?
에디터가 DDC 데이터를 제대로 읽지 못하는 것 같다면, 로그 파일에서 LogDerivedDataCache
를 검색합니다.
LogDerivedDataCache: Display: Max Cache Size: 512 MB
LogDerivedDataCache: Loaded boot cache 0.07s 118MB ../../../EngineTest/DerivedDataCache/Boot.ddc.
LogDerivedDataCache: Display: Loaded Boot cache: ../../../EngineTest/DerivedDataCache/Boot.ddc
LogDerivedDataCache: FDerivedDataBackendGraph: Pak pak cache file ../../../EngineTest/DerivedDataCache/DDC.ddp not found, will not use a pak cache.
LogDerivedDataCache: Unable to find inner node Pak for hierarchical cache Hierarchy.
LogDerivedDataCache: FDerivedDataBackendGraph: EnginePak pak cache file ../../../Engine/DerivedDataCache/DDC.ddp not found, will not use a pak cache.
LogDerivedDataCache: Unable to find inner node EnginePak for hierarchical cache Hierarchy.
LogDerivedDataCache: Found environment variable UE-LocalDataCachePath=d:\DDC
LogDerivedDataCache: Using Local data cache path d:\DDC: Writable
LogDerivedDataCache: Using Shared data cache path \\epicgames.net\root\DDC-Global-UE: Writable
이 로그에서 다음과 같은 내용을 알 수 있습니다.
- 프로젝트 또는 Engine Pak 캐시가 없습니다. 이 빌드는 Perforce에서 직접 컴파일했기 때문에 예상되는 일입니다.
- 로컬 데이터 캐시 경로가 d:\DDC에 매핑되어 있으며 쓰기 가능합니다.
- 쓰기 가능한 에픽 공유 캐시를 사용하고 있습니다.
또한, -logcmds="LogDerivedDataCache Verbose"
를 실행하여 상세 로깅을 켤 수도 있습니다.
질문: S3 DDC가 무엇인가요?
포트나이트 DDC는 보유 콘텐츠 양 때문에 엄청나게 큽니다. 코로나19가 발생했을 때, 저희는 곧 개발자가 제한된 대역폭의 VPN을 통해 네트워크 공유에서 이 모든 데이터를 사무실로 가져오는 것이 매우 비효율적이라는 사실을 깨달았습니다. 그래서 대신 S3를 통해 가장 일반적으로 사용되는 데이터를 배포하고 있습니다.
S3DDC를 사용하도록 엔진을 구성하기는 매우 쉽지만, 자동으로 DDC 콘텐츠를 생성하고 S3에 업로드하도록 설정해야 합니다.
질문: IDDCUtilsModuleInterface가 무엇인가요?
플랫폼이나 도메인에 따라 런타임 시 동적으로 리졸브될 수 있는 Name 실행인자를 DDC 세팅에서 사용할 수 있게 해주는 인터페이스입니다.
안타깝게도 이 인터페이스에 대한 예시는 여기 없지만, 인터페이스 구현은 간단합니다.
#include "CoreMinimal.h"
#include "DerivedDataUtilsInterface.h"
#include "Modules/ModuleManager.h"
class FDCCUtilsModule : public IDDCUtilsModuleInterface
{
/** IDDCUtilsModuleInterface 구현 */
virtual FString GetSharedCachePath(const FString& CacheName) override;
/** IModuleInterface 구현 */
virtual void StartupModule() override;
/** 내부 DDC 서버 목록 */
TMap<FString, FString> NameToServerMap;
}
IMPLEMENT_MODULE(FDDCUtilsModule, DDCUtils)
void FDDCUtilsModule::StartupModule()
{
#if PLATFORM_MAC
NameToServerMap.Add(TEXT("?EpicDDC"), TEXT("/Volumes/UEDDC"));
NameToServerMap.Add(TEXT("?EpicDDC2"), TEXT("/Volumes/UEDDC2"));
NameToServerMap.Add(TEXT("?EpicSeaDDC"), TEXT("/Volumes/DDC"));
#elif PLATFORM_LINUX
NameToServerMap.Add(TEXT("?EpicDDC"), TEXT("/mnt/UEDDC"));
NameToServerMap.Add(TEXT("?EpicDDC2"), TEXT("/mnt/UEDDC2"));
NameToServerMap.Add(TEXT("?EpicSeaDDC"), TEXT("/mnt/DDC"));
#else
NameToServerMap.Add(TEXT("?EpicDDC"), TEXT("\\\\epicgames.net\\root\\DDC-Global-UE"));
NameToServerMap.Add(TEXT("?EpicDDC2"), TEXT("\\\\epicgames.net\\root\\UEDDC2"));
NameToServerMap.Add(TEXT("?EpicSeaDDC"), TEXT("\\\\sea.epicgames.net\\root\\DDC"));
#endif
}
FString FDDCUtilsModule::GetSharedCachePath(const FString& CacheName)
{
FString* ServerName = NameToServerMap.Find(CacheName);
if (ServerName)
{
return *ServerName;
}
else
{
return FString();
}
}
질문: DDC Pak은 어떻게 생성하나요?
프로젝트별 DDC 생성:
UnrealEditor.exe ProjectName -run=DerivedDataCache -fill -DDC=CreatePak
이 커맨드릿을 실행하면 프로젝트의 모든 콘텐츠에 대한 DDC가 생성됩니다. 아니면, 자동화 또는 사용자 세션을 실행하는 동안 간단히 -DDC=CreatePak을 제공하여 타깃이 더 명확한 콘텐츠 세트를 생성할 수도 있습니다.
엔진 DDC 생성:
UnrealEditor.exe -run=DerivedDataCache -fill -DDC=CreatePak