技术博客

模型导入:glTF/FBX 到 ImporterMesh 的转换与拆分策略

第 108 / 149 篇 · 2025-04-27 · godot · 资源管线3D工程实践

拖一个 .glb 进工程,直接实例化就能跑——但 imported 目录里其实躺着好几份产物:一份节点树、若干 mesh 资源、可能还有动画库。理解这套结构的意义在于做拆分决策:多人共用的模型资产怎么组织,动画从哪来,以及为什么官方推荐工作流是"DCC 里导出 glTF,别折腾 FBX"。

两条解析路径,一个终点

glTF:一等公民。 modules/gltf 是引擎内置模块,纯 C++ 解析器,无外部依赖,.gltf(JSON + 外部 bin)和 .glb(二进制打包)都直接读。它是官方推荐管线的原因很实际:规范开放、字段映射干净(节点/网格/蒙皮/动画都有标准表达)、没有版本碎片化问题。

FBX:兼容义务。 FBX 是 Autodesk 的私有格式,闭源、版本多、语义曲折。Godot 4.3 之前靠外部转换器(FBX2glTF)先把 FBX 转成 glTF 再进管线,多一个进程就多一批"转换后和 DCC 里不一样"的归因难题;4.3 起换成内置的 ufbx 库直接解析,路径短了,但格式的天然复杂度还在——嵌套的变换枢纽(pivot)、多套单位制、非标准轴向,都是翻译损耗的高发区。能出 glTF 就出自 DCC,FBX 只留给拿不到 glTF 的旧资产。

两条路径的终点是同一个中间结构:ImporterScene(节点树骨架)+ ImporterMesh(网格数据)。ImporterMesh 是导入期的中间态——它带着 LOD 数组、各 surface 的顶点数据、材质槽,导入完成后被编译成运行时的 ArrayMesh 存进 .godot/imported/ 的产物文件。

产物结构:一份树,多份资源

导入一个角色模型的产物布局:

角色.glb
  ├── 节点树(Node3D 层级:骨架、MeshInstance3D、碰撞)
  ├── ImporterMesh → 编译为 ArrayMesh(每个 mesh 资源独立寻址)
  ├── 材质(内嵌 glTF 材质的翻译结果)
  └── 动画(AnimationClip 集,可指定进 AnimationLibrary)

运行时 instantiate 这份场景,节点树直接激活,MeshInstance3D 通过 mesh 属性引用共享的 mesh 资源。拆分策略的核心问题就在这:mesh 数据要不要从场景里提出来单独存?

  • 一个模型只在一个场景用:默认即可,mesh 随场景走,无决策成本。
  • 多个场景共享同一模型(同一张桌子摆二十个房间):把 mesh 提出来(导入面板 "Extract" 相关选项,或按路径手动保存为 .res),场景里用 load() 引用同一份。共享的是顶点数据,实例间的差异只在 Transform——配合 MultiMesh(GPU 实例化那篇)走得更远。
  • 只要网格不要场景(程序化生成关卡、自定义组装):导入模式从 "Scene" 切到只取 mesh 资源。

动画是独立的拆分维度:导入时可指定把动画导出为 AnimationLibrary 资源——同一套攻击动画给不同骨架的角色复用(重定向那篇的现实),就靠库层共享、骨骼层映射。

三个默认就踩的坑

单位。 glTF 规范是米,FBX 常见厘米(且 FBX 文件里自己记着单位)。Godot 导入时按源单位换算到引擎的米制——通常正确,但 DCC 导出设置和单位实际不符时(Blender 场景单位调成 0.01 之类),模型进来大一百倍或矮一半。判断方法:拖一个 1.8 m 的胶囊体对比,比例不对先查 DCC 导出设置,别在导入面板乱调 scale 掩盖病因。

坐标系。 glTF 是 Y-up、右手系,Godot 是 Y-up、左手系。导入时做 Z 翻转换算,glTF 的 +Z 前进变成引擎的 -Z 前进。绝大多数情况翻译正确,代价是"模型在 DCC 里朝 +Z,进了引擎朝 -Z"的认知差——给模型定朝向约定时(比如角色朝向),以引擎里为准反推 DCC。

材质。 glTF 的 metallic-roughness 工作流翻译最顺(PBR 参数一一对应);FBX 常见 specular-glossiness 材质,转换要近似,金属度贴图经常整个翻译丢。导入后第一件事是检查材质球的 metallic 通道——FBX 进来的模型材质发灰发白,八成是这张图的翻译问题,手动接回 ORM 通道即可。

导入期的决策清单

模型进工程按这个顺序过一遍:先定拆分(场景独享 / mesh 提取共享 / 纯 AnimationLibrary),再核对三个坑(单位、朝向、材质金属度),最后看一眼 LOD——ImporterMesh 保留了 DCC 导出的 LOD 链,导入设置里确认 LOD 数量和切换距离,别等性能那篇的 profiler 报 polycount 超标再回来补。

模型导入管线:两条源格式,一个中间结构 .glb / .gltf 内置 GLTFDocument 解析 .fbx ufbx(4.3 起内置) ImporterScene + ImporterMesh 中间态:LOD/surface/材质槽 场景节点树(.scn 产物) 实例化即激活 ArrayMesh(编译后) 可提取共享 / MultiMesh 拆分策略 场景独享:默认 │ 多场景共享:mesh 提取为 .res │ 复用动画:导成 AnimationLibrary 三个默认就踩的坑 单位(FBX 厘米 vs glTF 米)│ 坐标系(Z 前进翻转)│ 材质(FBX 金属度贴图翻译丢失)