资产管线与工具链
Asset Conditioning Pipeline & Tools
游戏引擎的输入数据来自美术使用的数字内容创作 (DCC) 工具,但 DCC 格式几乎从不直接用于游戏,必须经过资产调理管线 (Asset Conditioning Pipeline, ACP) 导出、处理并按平台打包。围绕它还有世界编辑器、记录资产元数据的资源数据库,以及几种工具架构(独立工具、与引擎共享底层、编辑器内嵌于引擎、Web 界面),各有取舍。
从 DCC 到游戏
美术用 Maya、3ds Max、ZBrush、Photoshop、Houdini、Sound Forge 等 DCC 应用制作源数据;有些数据(如关卡布局)通常由引擎自带编辑器制作。Gregory 强调工具不必漂亮,但必须易用、可靠(卷 I 1.6.1)。
DCC 格式不适合直接进游戏,原因有二(卷 I 1.6.2):
- DCC 的内存模型远比引擎需要的复杂。例如 Maya 保存场景节点的有向无环图 (DAG)、全部编辑历史、分解为平移/旋转/缩放/切变的完整变换层级,而引擎只需要其中一小部分。
- DCC 文件格式运行时读取太慢,有时还是封闭的专有格式。
因此数据先导出为标准或自定义的中间格式,再进一步处理:例如把同材质网格合并、把过大的网格拆开,最后打包成适合某个平台直接载入的内存映像;多平台发行时同一中间文件按平台分别处理。这条从 DCC 到引擎的流水线就是 ACP,每个引擎都有某种形式的 ACP。
下图概括书中图 1.33 的数据流向(粗略合并了各类资产):
flowchart LR
DCC["DCC 工具:Maya / Max / Blender / ZBrush / Photoshop / Houdini / 音频软件"] --> EXP["导出器:网格、骨骼层级、动画、粒子"]
EXP --> MID["中间格式"]
MID --> COND["调理:合并/拆分网格、纹理压缩(TGA→DXT)、打包声音库"]
ED["引擎自带编辑器:世界编辑器、对象模型编辑器、动画树编辑器"] --> COND
DB[("资源数据库:元数据")] --- COND
COND --> GAME["按平台打包的游戏数据"]左侧是美术工具,右侧是引擎最终读取的数据;资源数据库保存每个资产如何被处理的元数据。
各类资产的要点(卷 I 1.6.2)
- 网格:硬件几乎只光栅化三角形,四边形和细分曲面最终都要转成三角形。书中把单个可渲染形状叫“网格 (mesh)”,把包含多个网格、动画和元数据的复合对象叫“模型 (model)”。OBJ、COLLADA、USD 等通用格式都不完全适合游戏(书中说 COLLADA 或许是例外),所以团队常写自定义格式和导出器。ZBrush 等工具可把超高精度模型降为低精度模型加法线贴图。
- 骨骼动画:渲染蒙皮网格需要三类数据:网格本身、骨骼层级(关节名、父子关系、绑定时的基础姿势)、动画片段。多个网格共用一个骨骼时,骨骼最好单独导出;动画通常逐个导出,只加载在用的部分。未优化的动画是每个关节每秒至少 30 个 矩阵采样,写实人形可能有 500 多个关节,所以动画数据几乎总是高度压缩,且没有统一格式。
- 音频:可能是单声道、立体声、5.1、7.1 等,常组织成声音库 (bank) 以便加载和流送。
- 粒子:Houdini 能做电影级效果,但引擎渲染不了全部,所以许多公司写自定义粒子编辑器,只暴露引擎支持的效果,并能所见即所得地预览。
世界编辑器与资源数据库
- 世界编辑器是所有东西汇合的地方,据作者所知没有可单独购买的通用世界编辑器;Quake 系用 Radiant 变体,Source 用 Hammer,Unreal 用 UnrealEd(它同时是全部数据类型的资产管理器),CRYENGINE 用 Sandbox(卷 I 1.6.3)。
- 资源数据库保存每个资产的元数据。以动画片段为例:运行时唯一 ID、源 Maya 文件路径、帧范围、是否循环、动画师选择的压缩方式与级别(有的资产能大幅压缩,有的必须少压缩甚至不压缩)。它可以是 MySQL 之类的关系数据库,也可以是由版本控制管理的一组文本文件;无论哪种都需要编辑界面,Naughty Dog 用 C# 写了叫 Builder 的工具(卷 I 1.6.4)。
工具架构的几种做法(卷 I 1.6.5)
| 做法 | 说明 | 取舍 |
|---|---|---|
| 独立工具 | 与运行时引擎完全分开 | 互不影响;但数据结构往往要在工具和引擎中各写一份 |
| 与游戏共享底层框架 | 工具建在核心系统、平台无关层等之上 | 复用底层代码 |
| 内嵌于游戏 | 如 Quake、Unreal 的游戏内控制台 | 开发者和 mod 作者可在运行中输入调试与配置命令 |
| 编辑器即引擎(UnrealEd) | 用命令行参数 editor 运行游戏就进入编辑器 | 工具能访问引擎全部数据结构,免去两套表示;在编辑器里运行游戏很快;游戏内实时编辑容易实现。但引擎一崩溃工具也不可用,紧耦合会拖慢生产 |
| Web 界面 | 如 Naughty Dog 的本地化工具 Cipher、调试信息查看器 Connector(引擎按系统分通道输出调试文本,存入轻量 Redis) | 开发维护更快、免安装、刷新即更新、天然客户端-服务器结构便于分发给外包伙伴;需要 3D 可视化等专门界面时仍要独立工具 |
与 UE 的对应
- UE 的 Build → Cook → Stage → Package 就是 ACP 的具体实现:烘焙把编辑器格式的资产转成目标平台格式,见 烘焙、打包与 Zen 加载器。
- 运行时如何引用和异步加载这些资产,见 资产管理与异步加载;书中所说“编辑器即引擎”的架构,正是 UE 编辑器的形态,其扩展方式见 编辑器扩展与 Python 脚本。
- 资产管线在整个引擎中的位置见 运行时引擎分层架构。
离线资源管理:版本控制、资源数据库与构建规则(卷 I 7.2.1)
GEA 第 7 章把资源管理器分为两个相互配合的部分:离线工具链(创建资产并转换为引擎可用格式)和运行时资源管理(见 资源管理器)。本节补充离线部分。
资产的版本控制(卷 I 7.2.1.1)
- 小项目可以把散落文件放在共享网络盘上;现代商业 3D 游戏资产数量和种类巨大,需要正式的管理方式。有些团队直接用源代码版本控制(美术把 Maya 场景、PSD、Illustrator 文件提交到 Perforce 等),也有团队写自定义资产管理工具(商业版本控制的简单包装或完全自研)来降低美术的学习成本。
- 数据量是最大问题:代码文件小,美术文件大得多;很多版本控制系统把文件从中央仓库复制到本地,资产体积可能让它们几乎没法用。作者见过的对策:
- 使用专为大数据设计的商业系统,如 Alienbrain;
- 「认了」,让版本控制工具照常复制到本地——磁盘够大、网络够快时可行,但低效;
- 在版本控制之上搭建复杂系统,确保每个用户只拿到自己真正需要的文件的本地副本,其余要么无权访问,要么按需从共享网络盘读取。
- Naughty Dog 的 NDFS:基于 Windows Projected Filesystem(Windows 10 2004 版及以后)的专有工具。用户看起来本地拥有仓库中的全部文件,但只有真正访问时才从服务器取回;需要编辑时 NDFS 代为签出 (check out)、给予独占修改权;提交后保证全工作室其他人自动「看到」最新版本——要么在用户读取该文件时才更新,要么在电脑空闲时于后台逐步更新。目前未商业化。
资源数据库(卷 I 7.2.1.2)
- 每个经过 ACP 的资源都有描述其处理方式的元数据:纹理用哪种压缩、动画导出 Maya 中哪段帧范围、多角色 Maya 场景中哪个网格对应游戏中哪个角色。小游戏可能只存在开发者脑子里(「玩家动画要勾 flip X,其他角色不要……还是反过来?」),有一定规模的游戏必须有半自动化资源管线,驱动它的数据存于某种资源数据库。
- 形式差异很大:元数据嵌入源资产(如 Maya 文件中的 blind data);每个源文件配一个描述处理方式的小文本文件;一组 XML 文件外加自定义 GUI;或真正的关系数据库(Microsoft Access、MySQL,甚至 Oracle)。
- 资源数据库必须提供的功能:处理多种资源类型(最好方式一致);创建、删除、查看与修改资源;移动资源源文件(美术和设计常因目标变化、设计调整、功能增删而重排资产);资源间交叉引用(网格用的材质、第 17 关需要的动画集合),它同时驱动构建过程和运行时加载;在删除、移动等常见操作下保持所有交叉引用的引用完整性;保留修订历史及「谁、为何修改」的日志;最好支持各种搜索查询(某动画用在哪些关卡、一组材质引用了哪些纹理、找一个一时想不起名字的资源)。
- 作者说设计良好的资源数据库「真的能决定一个团队是推出爆款,还是空转 18 个月后被管理层叫停」——他两种都亲身经历过。
几种成功的设计(卷 I 7.2.1.3)
| 设计 | 优点 | 缺点 |
|---|---|---|
| Unreal(UnrealEd) | 无所不包的「超级工具」,从元数据管理、资产创建到关卡布局;编辑器是引擎的一部分,资产创建后立即以游戏中的样子查看,甚至可在编辑器里运行游戏;Content Browser 提供「一站式」访问引擎用到的每个资源;资产必须显式导入,导入时即可验证,创建者立即得到反馈 | 资源数据存在少量大型二进制包文件中,CVS/Subversion/Perforce 难以合并,同一包同时只能一人锁定(拆成小包可缓解但无法根除);重命名/移动资源时用重定向占位对象把旧名映射到新名,这些对象会堆积并在删除资源时引发问题——引用完整性很好但不完美 |
| Naughty Dog | 《神秘海域:德雷克船长的宝藏》用 MySQL 存元数据并配自定义 GUI(用户无需学 SQL);后改为 Perforce 管理的 XML 文件数据库。GUI 工具 Builder:左侧资源树(文件夹可随意组织 actor、level 及网格、骨骼、动画等子资源),右侧属性窗口;动画可归入称为 bundle 的伪文件夹整体管理。资源粒度细(几乎不会两人同时改同一资源);功能够用不多做;源文件映射清晰;改导出处理方式只需在 GUI 里调属性;命令行 ba 角色名 / bl 关卡名 构建,依赖系统处理其余 | 缺少可视化工具,只能载入游戏或模型/动画查看器(其实是游戏的特殊模式)预览;工具未完全整合:关卡布局、资源数据库、材质与着色器设置各用一个工具,构建在命令行——整合的收益可能抵不过成本,所以 ND 无此计划 |
| OGRE | 运行时资源管理器完善、接口统一、易扩展新资源类型 | 只有运行时,没有离线资源数据库;Maya 导出器要在 Maya 里手动运行,导出元数据由导出者手工输入 |
| Microsoft XNA(2014 年退役) | 借用 Visual Studio 的项目管理与构建系统来管理和构建资产;Game Studio Express 只是 Visual Studio Express 的插件 | — |
- 原版 MySQL 方案的问题:没有有用的修改历史、难以回滚错误修改、不支持多人编辑同一资源、难以管理。ND 的管线由命令行运行的资源导出器、编译器、链接器组成,资源最终打包为两类文件:actor(骨骼、网格、材质、纹理、动画)和 level(静态背景网格、材质、纹理及关卡布局),构建工具查询数据库决定如何从 Maya、Photoshop 导出、如何处理、如何打包成
.pak二进制文件——比许多需要美术手动导出的引擎简单得多。 - 与当前 UE 的对照(GEA 描述的是 UnrealEd 时代的情况):书中的「重定向占位对象」在 UE 中叫 Object Redirector,编辑器提供「Fix Up Redirectors」命令批量修复引用并删除它们(Epic 文档「Asset Redirectors」);UE5 的 One File Per Actor (OFPA) 把关卡中每个 Actor 存为独立外部包文件,正是为缓解书中所说「多人不能同时改同一关卡包」的锁定问题(Epic 文档「One File Per Actor」)。二者并不否定书中的论述,只说明问题在新版中有了官方缓解手段。
- 与上文 1.6.4 的说法对照:上文据 GEA 1.6.4 写 ND 用 C# 写了 Builder;7.2.1.3 补充了它背后数据库从 MySQL 到 Perforce 管理的 XML 的演变,两处一致。
ACP 的三个阶段(卷 I 7.2.1.4)
ACP 也叫资源调理管线 (RCP) 或工具链。源资产(Maya .ma/.mb、Photoshop .psd 等)通常经过三个阶段:
- 导出器 (exporter):通常是 DCC 的自定义插件,把数据导出为中间格式。Maya 提供 C++ SDK、MEL 脚本语言和 Python 接口三种方式。DCC 没有定制钩子时,可存成其原生格式之一——幸运的话是开放格式、直观文本格式或可逆向的格式——直接交给下一阶段。
- 资源编译器 (resource compiler):把导出的原始数据「按摩」成游戏可用的形式,如把网格三角形重排成条带 (strip)、压缩纹理、计算 Catmull-Rom 样条各段的弧长。并非所有资源都需编译。
- 资源链接器 (resource linker):把多个资源文件组合成一个包再交给引擎,类似把 C++ 目标文件链接成可执行文件。如复杂 3D 模型要合并多个网格、材质、一个骨骼和多个动画文件。并非所有资源都需链接。
资源依赖与构建规则
- 资产像源代码一样有相互依赖(网格引用材质、材质引用纹理),影响处理顺序(如先构建角色骨骼才能处理其动画),也决定某个源资产改动后哪些资产要重建。
- 数据格式变化同样触发重建:网格文件格式一变,全部网格可能都要重新导出/构建。有的引擎让格式能容忍版本变化(资产带版本号、引擎保留加载旧资产的代码),代价是资产文件和引擎代码臃肿;格式变化少时,不如咬牙全部重新处理。
- 每条 ACP 都需要描述依赖的规则和据此按正确顺序构建的构建工具:有的团队自研,有的用
make等现成工具。务必极其小心对待依赖系统,否则源资产改了而相关资产没重建,会产生不一致的资产,导致画面异常甚至引擎崩溃——作者见过无数小时浪费在本可避免的此类问题上。
GEA 的视角:渲染资产(卷 II 12.9.1、12.9.3)
- 从 DCC 到三角形:模型可以用 NURBS、四边形、三角形等任意表面描述制作,但在运行时光栅化前一定会三角化,要么离线在资产调理阶段完成,要么在 GPU 上由曲面细分实时完成(卷 II 12.9.1,工具总览见 渲染开发与 GPU 调试工具)。
- 一个 3D 模型由几何(顶点和索引缓冲)、材质、纹理和可选的骨架组成;ACP 保证模型引用的所有资产都齐备、可被引擎加载(卷 II 12.9.3)。
- 几何和材质数据从 DCC 导出,通常先存成平台无关的中间格式,再按目标平台处理成一种或多种平台专用格式。理想情况下,产物加载进内存后几乎不需要后处理:例如给 Xbox Series X 或 PS5 的网格直接输出为 GPU 可用的索引和顶点缓冲;而在 PS3 时代,几何会被输出成压缩数据流,DMA 给 SPU 解压。
- ACP 构建资产时常考虑材质和着色器的需要,例如某个着色器需要切线、副切线和顶点法线,ACP 可以自动生成这些向量。
- 场景图(空间划分)数据结构通常也在这一阶段生成:静态关卡几何可以处理成 BSP 树、四叉树、八叉树、包围球层次,或用于实时光追的 TLAS/BLAS 加速结构(见 空间数据结构、硬件光线追踪管线)。
- 补充说明:在 PC 的 DXR/Vulkan 上,加速结构的内存格式由驱动决定、不透明,通常只能在运行时构建;DXR 的序列化 (
CopyRaytracingAccelerationStructure的 SERIALIZE 模式) 产物只保证在同一设备和驱动上反序列化(Microsoft DirectX Raytracing 功能规范,"Acceleration structure serialization")。TLAS 引用实例变换,一般每帧重建或更新。离线阶段能做的主要是准备几何、划分 BLAS 粒度;固定硬件的主机平台才可能在离线阶段预先生成。GEA 这句话应按这个限制理解。
- 补充说明:在 PC 的 DXR/Vulkan 上,加速结构的内存格式由驱动决定、不透明,通常只能在运行时构建;DXR 的序列化 (
- 昂贵的光照计算也常在这里离线完成,即静态光照:烘焙顶点光照、光照贴图、PRT 系数(通常用球谐函数表示)等(见 预计算光照与光照贴图)。
GEA 的视角:平台相关优化在何时发生(卷 II 16.4.2)
GEA 第 16 章补充了"两步 ACP"的一个关键设计点:先导出为平台无关的中间格式,再处理成平台优化格式,而各引擎差别在于第二步何时做(卷 II 16.4.2.1):
- UnrealEd:资产首次导入编辑器时(GEA 的描述)。关卡迭代快,但改源资产更痛苦。
- Source、Quake:运行前烘焙关卡时。
- Halo:首次加载进引擎时转换并缓存,原始资产随时可改。
GEA 还把 UnrealEd 作为"世界编辑器与资产数据库集成"的代表:编辑器集成在引擎中,修改直接作用于运行中的游戏(卷 II 16.4.2),与上文 1.6.5 "编辑器即引擎"的说法一致。
分歧:UE 5.8 文档把平台格式转换放在打包流程的 Cook 阶段,见 烘焙、打包与 Zen 加载器;与 GEA "导入时完成"的描述并列记录。世界编辑器的功能清单见 数据驱动与游戏世界编辑器。
PBRT 的视角:场景描述的解析(PBRT 4e C.1–C.2.2、延伸阅读)
- 三段式:文本场景文件 → 解析器把每条语句转成
ParserTarget接口(近 40 个纯虚函数,每个对应一种语句)的一次调用 →BasicSceneBuilder跟踪图形状态,为每个实体产生一个*SceneEntity→BasicScene创建渲染用的对象。接口抽象的好处是可以换实现,例如FormattingParserTarget用来格式化场景文件并把旧版 pbrt 的语法升级为新版。 - 手写解析器:记号规则很简单(空白分隔、双引号字符串、方括号数组、
#注释)。旧版 pbrt 用 flex/bison;作者在加载数 GB 的迪士尼 Moana Island 场景时发现大量时间耗在解析机制本身,改为手写解析器后显著变快,还省掉了构建依赖。 - 参数字典:解析器只把
"float radius" 10这样的参数存成类型字符串、名称和四种基本值数组之一(float/int/string/bool),不做任何校验。ParameterDictionary负责类型检查和取值,支持 11 种参数类型,用 C++ 类型萃取 (type traits) 让每新增一种类型只需写一个声明式的特化;查找是 线性扫描,因为参数很少。光谱参数要区分光源、反射率(有界 [0,1])和无界三种,分别映射到不同的 RGB 光谱类。ReportUnused()对从未被读取的参数报错,用来发现拼写错误。 - 外部格式:pbrt 另外支持 PLY 网格(Greg Turk,1990 年代,有二进制编码);RenderMan 接口曾被采用,USD 目前在电影制作中广泛使用。练习 C.1 建议为 Moana 这样的场景设计更高效的二进制格式,并用
ParserTarget写转换器。
出处
- Game_Engine_Architecture_4Ed_-_Jason_Gregory.pdf
- Jason Gregory《Game Engine Architecture》第 4 版(2026)卷 I 第 1 章 1.6 节
- Jason Gregory《Game Engine Architecture》第 4 版(2026)卷 I 第 7 章 7.2.1 节
- Game_Engine_Architecture_4th_Edtion_Volume_2_-_Jason_Gregory.pdf
- Jason Gregory《Game Engine Architecture》第 4 版(2026)卷 II 第 12 章 12.9.1、12.9.3 节
- Jason Gregory《Game Engine Architecture》第 4 版(2026)卷 II 第 16 章 16.4.2 节
- PBRT 4e source excerpt: chapter C (Processing the Scene Description)
- Pharr, Jakob, Humphreys《Physically Based Rendering: From Theory to Implementation》第 4 版(MIT Press, 2023)附录 C C.1–C.4 节与延伸阅读,pbr-book.org/4ed/Processing_the_Scene_Description