UE5.7 解析:Incremental Cooking决策逻辑
前言
在 Unreal Engine 的 Cook Pipeline 中,UCookOnTheFlyServer::LoadBeginCookIncrementalFlagsLocal 负责在 Cook 任务启动初期,依据命令行参数、配置文件以及当前平台的状态,决定本次构建应当执行 Incremental Cook(增量构建) 还是 Full Cook(全量构建)。
一、 参数解析
在进入具体平台的处理逻辑之前,系统首先需要确定“全局构建目的”。这一阶段的核心变量为 bForceRecook,其值的确定遵循“配置默认值 -> 命令行覆盖”的优先级链条。
1. 默认策略初始化
系统首先通过 bDefaultIncremental 变量确立默认行为。
- 非 Legacy 模式(主要路径):通过读取
GEditorIni配置文件中的[CookSettings] CookIncrementalDefaultIncremental字段决定。若未配置,默认值为true。 - Legacy 模式:依据
ECookInitializationFlags::LegacyIterative标志位判定。
1 | |
2. 命令行参数的覆盖逻辑
命令行参数具有最高优先级,可直接修正 bForceRecook 的状态:
- 强制启用增量:
- 参数:
-CookIncremental或-CookIncremental=true - 效果:
bForceRecook = false - 注意:在 Legacy 模式下,若存在
LegacyIterativeflag,亦会将此值置为 false。
- 参数:
- 强制全量构建:
- 参数:
-fullcook、-forcerecook或-forcerecook=true - 效果:
bForceRecook = true
- 参数:
- DiffOnly 特殊模式:
- 参数:
-DIFFONLY - 效果:设置
bIsDiffOnly = true。此模式独立于常规增量逻辑,旨在进行差异比对而不修改磁盘上的资产。
- 参数:
至此,变量 bIncrementalOrLegacyIterative 被计算得出,它代表了本次构建的理论目的:
1 | |
二、 平台有效性验证
确定全局目的后,函数进入 BeginContext.PlatformContexts 循环,针对每一目标平台进行独立判断。增量构建是否被允许(bIncrementalOrLegacyIterativeAllowed),取决于Sandbox 状态与Settings Hash的一致性。
1. DiffOnly 模式
若 bIsDiffOnly 为真,逻辑将直接跳过常规判定:
- 结果:
bFullBuild = false,但bAllowIncrementalResults = false。 - 行为:系统将保留磁盘上的旧包,但仅将本次 Cook 结果写入内存用于比对,不会更新本地缓存。
2. 常规模式
若非 DiffOnly 模式,系统将通过以下两层检查来决定 bIncrementalOrLegacyIterativeAllowed 的最终值。
A. 初始化阶段的强制清理
当平台 Sandbox 尚未初始化 (!PlatformData->bIsSandboxInitialized) 且 全局目的为非增量 (!bIncrementalOrLegacyIterative) 时,系统将强制执行全量清理。
- 代码逻辑:
1 | |
- 日志特征:
- 若因配置导致:
FULL COOK: Incremental Cooks are disabled by default in Editor.ini... - 若因参数导致:
FULL COOK: -forcerecook=true (or an equivalent) was specified.
- 若因配置导致:
B. 配置一致性检查
即便全局目的允许增量,或 Sandbox 已初始化,系统仍需验证构建环境的一致性。系统会遍历所有 CookArtifact,加载上一次构建保存的配置与当前计算出的配置 (Current.Settings) 进行比对。
- 代码逻辑:
1 | |
- 日志特征:
FULL COOK: ... settings have changed and all previously cooked packages are invalidated.- 此日志表明
-CookIncremental虽然已指定,但由于 Global Settings 或 Artifact Settings 变更,增量被否决。
三、 最终确认
经过上述判定,PlatformData 的关键标志位将被最终赋值,这将直接指导后续 Cook 流程的行为。
1. 判定结果为 Allowed
当 bIncrementalOrLegacyIterativeAllowed == true 时:
bFullBuild = falsebAllowIncrementalResults = true:允许复用旧结果。bPopulateMemoryResultsFromDiskResults:若内存无结果,则允许从磁盘回填。- 日志:
INCREMENTAL COOK: ... settings are still valid.
2. 判定结果为 Not Allowed
当 bIncrementalOrLegacyIterativeAllowed == false 时:
bFullBuild = truebAllowIncrementalResults = falsebClearMemoryResults = true:清理内存中的旧记录。- 日志:参见上文的 FULL COOK 日志。
3. 安全约定检查
最终把结论写回 PlatformData
1 | |
后续 cook 流程会依据 PlatformData 的这些字段采取行为。
在函数末尾,存在一个关键的断言。若当前运行模式bFullBuildAllowed == false,但逻辑判定必须进行全量构建PlatformData->bFullBuild == true,系统将触发致命错误并中止进程,而非擅自执行清理。
1 | |
四、 总结
增量构建并非仅由命令行参数决定,而是一个多因素共同作用的动态决策过程:
- 命令行与 Ini 配置 决定了初始的构建目的。
- Sandbox 初始化状态 决定了冷启动时的清理策略。
- Artifact Settings 对比 构成了增量有效性的最后检查。
A. “增量”成功生效(即 bAllowIncrementalResults=true)必须满足所有条件:
- 不能是
-DiffOnly(DiffOnly 强制bAllowIncrementalResults=false)。 - 对该平台,不能落入“初始化时强制全量清理”分支:
- 也就是不能同时满足:
!bIncrementalOrLegacyIterative && !bIsSandboxInitialized - 实操上:平台首次初始化时,必须处于 incremental/iterative 大前提为真,否则必 full。
- 也就是不能同时满足:
- 设置对比不能要求全量:
- 任一 CookArtifact 的
CompareSettings()触发Context.IsRequestFullRecook(),则必然 full。
- 任一 CookArtifact 的
- 如果处于某些 validate/diff 契约模式导致
!bFullBuildAllowed,则还必须保证最终不被判成 full,否则直接 fatal。
B. “全量”的典型触发条件:
- 显式 forcerecook/fullcook,且平台 sandbox 尚未初始化。
- 新系统下 Editor.ini 配置
CookIncrementalDefaultIncremental=false,且没有用命令行显式把它改回允许增量(例如-CookIncremental或-forcerecook=false),并且平台 sandbox 尚未初始化。 - legacy 模式下未设置
LegacyIterativeflag(常见就是没带-legacyiterative),且平台 sandbox 尚未初始化。 - 设置变化触发
RequestFullRecook:无论是否请求增量,只要触发就 full(并打印 settings changed 的 FULL COOK 日志)。