DDC 是 派生数据缓存 的缩写。
许多 虚幻引擎 资产都需要额外的"派生数据"才能使用(比如包含着色器的材质就是一个简单示例)。材质在渲染之前,必须为运行编辑器的平台编译着色器。
由于派生数据很大,并且有时可能需要重新生成,因此不会将其检入源代码控制,而是保留在派生数据缓存 (DDC) 中。
DDC的存储位置
根据项目和系统的配置方式,可以存在多个DDC缓存(按照快慢顺序)。在评估派生数据时,你的系统将执行以下操作来确定访问速度:
- 当需要某条派生数据时,将首先检查最快的缓存,然后检查速度次之的缓存,依此类推,直到找到数据为止。
- 找到数据后,会将其复制到最快的本地缓存中,以便下次更快地访问。
- 如果未找到数据,则将首先生成数据,然后将其异步复制到缓存中,以便供你(甚至可能是你的团队)将来使用。
存储在DDC中的内容允许使用后即丢弃,因为它可以随时使用保存在.uasset文件中的数据重新生成。通过将这些派生格式存储在外部,我们可以轻松地添加或更改引擎使用的格式,而不需要修改源资产文件。
DDC类型
通常,你将至少拥有以下两个缓存:
- 启动DDC: 加载到内存中以便提升启动时间的启动文件。
- 例如:ProjectDir/DerivedDataCache/Boot.ddc
- 本地DDC: 项目的派生数据。
- 例如:EngineDir/DerivedDataCache
但是,你的项目也可以设置为使用 DDC Pak 或 共享DDC。
DDC Pak
如果你从Epic Games商店下载虚幻引擎,则该引擎将附带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:网络驱动器或映射驱动器。
共享驱动器的示例将为:\epicgames.net\root\DDC-Global-Fortnite
使用共享DDC
工作室应该使用一个所有特定位置的用户都可以访问的共享DDC。这样,只有一个用户需要构建派生的资产格式,然后这些格式将自动供所有其他用户使用。虽然需要处理资产时偶尔会出现卡顿,但是结果将被保存和共享。即使在相当小的团队中,以这种方式共享资产处理工作也会大大地减少处理时间。
不建议通过互联网复制整个DDC、备份DDC或从备份还原DDC。虽然上述操作不会造成任何损害,但它们会浪费时间,因为传输存储在DDC中的数据量要比在本地从头生成数据花费更长的时间。如果你有一个大型项目,并希望分发预构建DDC数据,你应该生成DDC Pak。
设置共享DDC
如你在 BaseEngine.ini
中看到的那样,编辑器已设置为使用共享DDC,该共享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数据比生成DDC数据花费的时间更长。要暂时禁用共享DCC,请使用以下方法之一:
- 在命令行上传递-ddc=noshared。
- 将环境变量设置为本地硬盘驱动器:
UE-SharedDataCachePath=None
- 在Mac上:
UE_SharedDataCachePath=None
构建派生数据
导入资产的用户是构建派生数据的用户,因为他们最有可能在引擎中使用和测试该资产。但是,有时也可能会出现新资产需要处理的情况。这种情况会根据需要自动出现,而且在涉及高性能硬件时应当影响不会太大,尽管可能会出现偶尔的卡顿。
你可以通过运行以下命令随时填充你的DDC:
UE4\Engine\Binaries\Win64\UE4Editor.exe ProjectName -run=DerivedDataCache -fill
虽然Epic Games每夜都会执行此操作,以确保DDC始终处于就绪状态,但这项工作并非必不可少,因为常规的自动缓存功能应当已能满足需要。
挂载你的DDC文件夹
如果是内部网络上使用的DDC,必须将包含DDC的文件夹挂载到网络驱动器上。如果你不熟悉此操作,请参阅在Windows上映射网络驱动器。
使用DDC进行发布
烘焙是打包游戏的首选方法,因为烘焙后的版本不需要或不使用DDC。但是如有需要,可以将DDC打包发布。
烘焙是打包游戏的首选方法,因为烘焙后的版本不需要或不使用DDC。但是如有需要,可以将DDC打包发布。
若要将DDC打包,请执行以下操作:
-
从UE4/Engine/Binaries/Win64目录运行UE4Editor.exe,传递如下所示的参数:
UE4Editor.exe ProjectName -run=DerivedDataCache -fill -DDC=CreatePak
- 这会在UE4\ProjectName\DerivedDataCache目录中创建DDC.ddp文件。
- 引擎将自动检测和使用.ddp文件。
DDC设置
DDC设置保存在哪里?
DDC设置保存在 [DerivedDataBackendGraph]
分段的 DefaultEngine.ini
中。你可以在 BaseEngine.ini.
中查看默认值。
[DerivedDataBackendGraph]
;保留文件至少7天
MinimumDaysToKeepFile=7
;配置根条目。它使用KeyLength节点对长字符串进行哈希处理,然后将请求传递给AsyncPut
Root=(Type=KeyLength, Length=120, Inner=AsyncPut)
;配置AsyncPut条目。它使用AsyncPut节点,然后将请求传递到层级
AsyncPut=(Type=AsyncPut, Inner=Hierarchy)
;配置层级条目。这将使用多个节点,这些节点按顺序使用,直到找到读取内容(写入将转到所有可写条目)
Hierarchy=(Type=Hierarchical, Inner=Boot, Inner=Pak, Inner=EnginePak, Inner=Local, Inner=Shared)
;配置Boot节点。这将保留用于加速启动的512MB数据
Boot=(Type=Boot, Filename="%GAMEDIR%DerivedDataCache/Boot.ddc", MaxCacheSize=512)
;配置本地节点。这是具有以下设置的filesystem节点 -
; Readonly: 能否将数据写入此层
; Clean: 在启动时执行旧文件清理
; Flush: 破坏DDC并重新开始
; PurgeTransient: 不要将瞬态数据保留在DDC中
; DeleteUnused: 清理旧文件(在后台线程上进行)
; UnusedFileAge: 文件删除前保留时长
; FoldersToClean: 会话中要清除的最大文件夹数。-1 = 无限
; MaxFileChecksPerSec: 每秒检查的文件数量。
; Path:文件系统DDC使用的路径
; EnvPathOverride: 环境变量,如果设置,将用于代替路径。如UE-LocalDataCachePath=d:\DDC。( 'None' 会禁用DDC)
; CommandLineOverride: 优先于默认值/envvar设置使用的命令行参数。如-SharedDataCachePath=\\someshare\folder
; EditorOverrideSetting: 覆盖默认/envvar/命令行值的编辑器用户设置
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 Commandlet创建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
运行编辑器。
在Epic,我们这样做有以下三个原因:
- 面向想要使用自己的DDC而不是全局DDC的办公室团队。
- 在创建DDC Pak时,我们使用其中一个选项控制.pak文件中的内容,例如
[CreateInstalledEnginePak]
。 - 面向因网速较慢或未启用VPN,而不想使用共享DDC的在家办公人员。
你会看到,默认情况下,BaseEngine.ini
包含多个DDC条目,包括NoShared,该条目用于上面第3条(-ddc=NoShared
)。
问:我的磁盘空间不足。我是否可以将本地DDC移到其他位置?
可以! 你可以打开项目,在编辑器的偏好设置中调整这个选项。此外,你可以将环境变量 UE-LocalDataCachePath
设置为你选择的路径即可。例如:UE-LocalDataCachePath=d:\DDC
。
- 在命令提示中,输入
"setx UE-LocalDataCachePath d:\DDC"
。 - 重新启动虚幻引擎,以及你任何相关的应用程序,例如Epic启动器、UGS或Visual Studio。
当主驱动器上的空间不足时,或者你在多个分支工作并希望确保数据不重复时,可以使用此方法
问:我的网络连接速度很慢。我是否可以关闭共享DDC?
可以! 有两种方法,具体取决于你希望临时还是永久关闭:
- 如果你将DDC的环境变量设置为
无
,它将禁用共享DDC。在这种情况下,你将设置UE-SharedDataCachePath=None
。 - 使用
-ddc=noshared
启动编辑器。
问:我是否可以更改共享DDC路径?
可以! 你可以通过设置上述 UE-SharedDataCachePath
更改共享DDC路径。
但是,永远不要将 UE-SharedDataCachePath
设置为本地路径!这样做意味着你将同时占用计算机上的本地缓存和共享缓存——两倍的磁盘空间占用量,且收益为零!
问:我如何诊断DDC问题?
如果你认为编辑器无法正确读取DDC数据,请在日志文件中搜索 LogDerivedDataCache
。
LogDerivedDataCache: 显示:最大缓存尺寸:512MB
LogDerivedDataCache: 已加载启动缓存0.07s 118MB ../../../EngineTest/DerivedDataCache/Boot.ddc.
LogDerivedDataCache: 显示:已加载启动缓存:../../../EngineTest/DerivedDataCache/Boot.ddc
LogDerivedDataCache: FDerivedDataBackendGraph: 未找到Pak pak缓存文件../../../EngineTest/DerivedDataCache/DDC.ddp,将不会使用pak缓存。
LogDerivedDataCache: 无法找到用于分层缓存层级的内部节点Pak。
LogDerivedDataCache: FDerivedDataBackendGraph: 未找到EnginePak pak缓存文件../../../Engine/DerivedDataCache/DDC.ddp,将不会使用pak缓存。
LogDerivedDataCache: 无法找到用于分层缓存层级的内部节点EnginePak。
LogDerivedDataCache: 找到环境变量UE-LocalDataCachePath=d:\DDC
LogDerivedDataCache: 使用本地数据缓存路径d:\DDC: 可写入
LogDerivedDataCache: 使用共享数据缓存路径\\epicgames.net\root\DDC-Global-UE4: 可写入
此处你可以看到:
- 没有项目或Engine Pak缓存,这是我自己从Perforce编译此版本时的预期结果。
- 我的本地数据缓存路径映射到d:\ DDC,并且可以写入。
- 我正在使用可写入的Epic共享缓存。
你也可以使用 -logcmds="LogDerivedDataCache Verbose"
运行,以便打开冗余日志记录。
问:什么是S3 DDC?
我们的内容量导致《堡垒之夜》DDC极其大。在新型冠状病毒肺炎爆发后,我们很快意识到,开发人员通过VPN的有限带宽从网络共享中提取所有这类数据到办公室的效率非常低,因此,我们通过S3分发了最常用的数据。
设置引擎使用S3DDC非常容易,但是你将需要设置自动生成DDC内容并将其上传到S3。
问:什么是IDDCUtilsModuleInterface?
此接口可以让你使用哪些内容?命名DDC设置中的参数,然后可以在运行时基于平台或域动态解析这些参数。
遗憾的是,我们没有提供示例,但是实现很简单:
#include "CoreMinimal.h"
#include "DerivedDataUtilsInterface.h"
#include "Modules/ModuleManager.h"
class FDCCUtilsModule : public IDDCUtilsModuleInterface
{
/** IDDCUtilsModuleInterface implementation */
virtual FString GetSharedCachePath(const FString& CacheName) override;
/** IModuleInterface implementation */
virtual void StartupModule() override;
/** List of internal DDC servers */
TMap<FString, FString> NameToServerMap;
}
IMPLEMENT_MODULE(FDDCUtilsModule, DDCUtils)
void FDDCUtilsModule::StartupModule()
{
#if PLATFORM_MAC
NameToServerMap.Add(TEXT("?EpicDDC"), TEXT("/Volumes/UE4DDC"));
NameToServerMap.Add(TEXT("?EpicDDC2"), TEXT("/Volumes/UE4DDC2"));
NameToServerMap.Add(TEXT("?EpicSeaDDC"), TEXT("/Volumes/DDC"));
#elif PLATFORM_LINUX
NameToServerMap.Add(TEXT("?EpicDDC"), TEXT("/mnt/UE4DDC"));
NameToServerMap.Add(TEXT("?EpicDDC2"), TEXT("/mnt/UE4DDC2"));
NameToServerMap.Add(TEXT("?EpicSeaDDC"), TEXT("/mnt/DDC"));
#else
NameToServerMap.Add(TEXT("?EpicDDC"), TEXT("\\\\epicgames.net\\root\\DDC-Global-UE4"));
NameToServerMap.Add(TEXT("?EpicDDC2"), TEXT("\\\\epicgames.net\\root\\UE4DDC2"));
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:
UE4Editor.exe ProjectName -run=DerivedDataCache -fill -DDC=CreatePak
此命令将为项目中的所有内容创建DDC。或者,你可以在运行自动化时仅提供-DDC=CreatePak,或者甚至提供用户会话,以便生成更有针对性的内容集。
创建引擎DDC:
UE4Editor.exe -run=DerivedDataCache -fill -DDC=CreatePak