← ALL ARTICLES

资产构建与发布

全库目录221
本文目录25

资产管线要把制作源转换成引擎可用、可追踪、可回滚的发布物。成熟流程不依赖某个人记住所有选项,而是把契约、验证、转换和状态写入工具与记录。

数据流

一条典型链路:

text
Authoring Source
  -> DCC Validation
  -> Export / Interchange
  -> Staging
  -> Engine Import
  -> Derived Data
  -> Runtime Cook / Bundle
  -> Publish Manifest

每一步都应知道输入、输出、工具版本和失败状态。直接把 DCC 文件拖进最终目录,会把导出选项、依赖和人工修复隐藏在个人电脑中。

资产身份与可重复构建

资产身份

文件名会改,目录会移动,稳定身份不应只依赖路径。引擎常使用 GUID、包路径或内部资产 ID 管理引用。

命名规范仍有价值,它服务人类检索、批处理和类型判断。但重命名和移动必须通过理解引用的 API 完成,不能让文件管理器移动后再人工修断链。

一个资产 Record 可包含:

  • 稳定ID;
  • Logical Name/Type;
  • 源数据路径与负责人;
  • 输出路径;
  • 依赖;
  • Tool/结构版本;
  • 内容哈希;
  • Publish 状态。

导入器的编译职责

导入器把交换格式翻译成引擎内部数据,和编译器很像:

  • 解析源数据;
  • 校验数据模式;
  • 规范化坐标与属性;
  • 生成网格/纹理/Animation/材质;
  • 计算派生数据;
  • 写依赖与诊断。

同一输入、配置和工具版本应产生相同输出。缓存键还要包含真实影响结果的依赖,发布物再记录输出哈希;输入键证明缓存命中条件,输出哈希则检验生成结果。若导入依赖当前选择集、时间、随机数或机器绝对路径,CI 和其他成员就难以复现。

哈希与增量构建

是否需要重建应由内容与配置决定,而不是只看文件修改时间。可计算:

Hbuild=Hash(Hsource,Hsettings,Vtool,Vschema,Hdeps)H_{build}=Hash(H_{source},H_{settings},V_{tool},V_{schema},H_{deps})

例如贴图T经压缩生成T平台,材质M引用其内容身份,包B收集两者。T像素变化但路径未变,T平台键必须变化;B也需记录新对象。若M只保存稳定资产ID而没有内嵌贴图字节,它可能无需重新编译;失效传播依据边的含义,而非所有引用无条件重建。清单中保留输入身份与输出哈希,才可检查更新到了哪层。

构建键不变且缓存产物校验有效时复用;输入变化使直接消费其内容的节点失效,再按依赖边语义传播,单纯运行时引用不必强制重新转换源资产。

哈希只说明输入相同,不保证工具本身确定性。多线程顺序、浮点、压缩器和未固定随机种子仍可能让输出不同。可在 CI 对同一输入构建两次比较哈希。

分层验证

验证器的层级

验证可以分为:

  • 结构:文件可读、数据模式、对象/骨骼/材质槽存在;
  • 规范:命名、目录、单位、轴向、枢轴;
  • 预算:顶点、纹理尺寸、骨骼、骨骼影响、材质/LOD 数量;
  • 语义:法线/切线、颜色空间、根运动、碰撞;
  • 依赖:缺失贴图、循环引用、Editor-only 引用、重复资源;
  • 运行时:平台格式、内存、着色器 Variant、Cook 与加载测试。

每条规则应有稳定规则编号、严重程度、对象位置、实际值、期望值和修复建议。只打印“资源错误”无法让美术自助解决。

错误、警告与信息

严重程度代表是否阻止发布:

  • 错误:数据错误、构建失败或确定违反上线预算;
  • 警告:有风险但存在合理例外;
  • 信息:统计、建议或可优化项。

规则应允许按资产类型和平台配置。主角与远景道具不应使用同一顶点上限。例外必须有原因、负责人和过期时间,不能通过关闭整个规则解决。

Auto-fix 的边界

安全 Auto-fix 通常满足:结果确定、可预览、可撤销、不会丢失创作信息。例如:

  • 规范文件名大小写;
  • 创建缺失目录;
  • 设置已确认的导入预设;
  • 清理无引用的空材质槽;
  • 生成缺失的元数据。

高风险操作应只报告或在副本中处理:重新拓扑、合并骨骼、覆盖源文件、改变 UV、强制压缩有损贴图。

批量修复前输出变更预览计划,列出将修改的文件、规则和前后值。

DCC 侧与引擎侧分工

DCC 侧更适合检查:

  • 非法历史、隐藏对象、Freeze/变换;
  • 骨架、约束、烘焙 Range;
  • UV、Non-manifold、命名和导出集;
  • 源数据纹理与引用路径。

引擎侧更适合检查:

  • 实际导入顶点/索引/骨骼;
  • 材质/着色器/纹理设置;
  • LODGroup、碰撞、包围范围;
  • 运行时 Reference、资源包与平台预算。

同一规则可两端各检查一次,但错误信息要区分“源数据错误”和“导入配置错误”。

导入预设与规则匹配

导入器设置应按资产类型/路径/元数据匹配,而不是所有文件同一配置。例如:

  • 角色网格导入蒙皮与形状目标,道具不导入;
  • 屏幕固定像素大小的 UI 可关闭 Mipmap,缩放或世界空间 UI 按采样需求决定;世界空间纹理通常开启;
  • 法线贴图使用数据语义和平台压缩;
  • Lightmap UV 只对特定静态网格生成;
  • 动画片段使用对应压缩误差。

自动修改导入设置可能触发重新导入。脚本必须防止导入回调递归,且只在配置真正变化时写回。

派生数据与依赖维护

派生数据

LOD、碰撞、Lightmap UV、纹理 Compression、着色器编译和平台网格都属于可再生成数据。它们应由源数据 + 设置重建,尽量进入共享缓存而不是让每个人提交机器产物。

但昂贵且不可稳定重建的离线模拟/烘焙可能需要版本化。判断标准是:重建时间、许可证、确定性、来源可用性和审查需求。

数据模式与迁移

资产元数据、导入器 Setting 和运行时数据都会演进。每份可持久化数据应记录结构版本,读取时执行显式迁移:

text
v1 -> v2 -> v3 -> current

迁移函数应可测试、可重复运行,并保留未知字段或给出明确错误。直接用当前默认值覆盖旧字段,会让资产表面“导入成功”,实际语义已经改变。

批量迁移前先扫描影响数量和不可逆步骤,生成备份/Changeset。迁移后运行重新导入、引用和目标平台 Cook,不能只检查序列化文件能打开。

依赖图与循环

导入顺序来自依赖 Graph。纹理可先于材质,材质可先于 Prefab/关卡;图中有环时,简单拓扑排序无法执行。

需要区分真正构建依赖和运行时软引用。可以通过稳定ID/Deferred Resolve 打断非必要强依赖。对不可避免的环,先建立对象壳,再进行第二阶段引用解析,而不是依赖文件枚举顺序。

依赖变化要触发正确下游失效。若材质只记录纹理路径而未进入依赖数据库,纹理更新可能不会使资源包重建。

重新导入与人工修改

自动重新导入不能覆盖引擎内人工数据。应明确哪些字段由源数据 Authoritative,哪些是 Engine 覆盖配置。

例如网格几何来自 FBX,但碰撞、LOD 屏幕尺寸或材质覆盖配置可能在引擎维护。导入器应保留这些覆盖配置,或把它们放入独立配置资产。若必须覆盖,应在预览中显示丢失内容并阻止静默执行。

发布与追溯

暂存与原子发布

构建不应直接覆盖当前正式版本。先写 Staging:

  1. 生成全部输出;
  2. 运行验证与加载测试;
  3. 写清单;
  4. 成功后原子切换 Published 指针/版本;
  5. 失败则保留上一版本。

这样可以避免批处理到一半时正式目录处于新旧混合状态。

文件移动在同一卷上可能原子,但跨系统发布通常需要版本目录和指针/数据库状态,不应假设复制整个文件夹是原子操作。

发布指针的并发约束

两个构建都从版本 12 开始,较新的构建先发布 14,较旧的构建随后完成 13。如果切换指针只执行无条件覆盖,正式版本会退回 13。发布器应在切换时检查预期旧版本或发布序号,并按项目规则拒绝过期结果。

text
validate all outputs and their hashes
write immutable version directory and manifest
compare-and-swap publishedPointer(expectedVersion, newVersion)
if conflict: report competing publish and retain staged outputs

这里的比较交换由存储或数据库的原子条件更新提供;普通“先读再写文件”不能保证并发安全。回滚同样切换到已验证的完整版本,运行中的读取者先固定版本身份,再读取该版本的全部依赖,避免跨文件读到两代内容。

清单与数据血缘

Publish 清单记录:

  • 资产 ID 与发布版本;
  • 源数据/依赖哈希;
  • Tool、插件、Engine 和结构版本;
  • 构建参数与目标平台;
  • 输出文件、大小和哈希;
  • 验证器结果与批准例外;
  • 构建者、时间、CI Job/Commit。

出现问题时应能从运行时资源追溯到源数据、设置和工具版本,也能查一个源数据影响哪些资源包/关卡。

用户可读的失败报告

报告按资产和责任分组,不要输出几万行无结构日志。每项提供:

  • Rule ID + Severity + Asset;
  • 问题位置;
  • 实际/期望;
  • 能否 Auto-fix;
  • DCC/引擎中的定位方式;
  • 文档链接。

批处理结束要给汇总:成功、警告、失败、跳过和耗时。错误日志应可保存为 JSON 供 CI 和看板使用,也有人类可读 HTML/Markdown。

发布门禁

门禁可以逐步提高:

  • 本地保存时快速检查;
  • 提交前检查受影响资产;
  • CI 对变更集做完整验证器/Cook;
  • 夜间任务对全库与目标设备做回归;
  • 发布构建使用冻结工具链和更严格预算。

本地反馈必须快。把所有检查都推到夜间 CI,会让错误隔天才返回,修复上下文已经丢失。

验证方法

  • 用合法、边界和故意损坏的 Fixture 测每条验证器。
  • 同一资产重复导入,确认无无意义差异和无穷重新导入。
  • 修改源数据、设置、工具版本、依赖,确认增量失效范围正确。
  • 模拟中途失败,确认 Published 版本不被破坏。
  • 从清单反查源数据和从源数据查询下游依赖。
  • 在至少一个目标平台执行 Cook/Load,不以 Editor 预览代替运行时验收。

相关主题

参考资料