关于 scenario-blender-export
scenario-blender-export 是用于将 Blender 资产交付到游戏引擎、Web 格式、USD 流程或 3D 打印的技能。它结合各目标的导出预设、交付审核和重新导入比对,检查仅凭导出成功无法发现的差异。
主要功能
- 01使用面向引擎的预设导出
- 02导出前审核资产
- 03重新导入并比对导出文件
- 04汇总 GLB 内容和扩展
- 05生成 LOD 与碰撞网格
- 06批量转换支持的模型格式
适用场景
- 01为 Unity 或 Unreal Engine 准备角色 FBX
- 02为 Godot 或 Web 导出 GLB
- 03通过往返比对检查模型差异
- 04转换模型文件夹并查看报告
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ scenario-labs/ skills --skill scenario-blender-export安装后在 Claude Code 中输入/scenario-blender-export确认已加载。
附带文件references/engines.mdscripts/bx_export.py
详细介绍
Blender 导出(引擎就绪文件)
只有在文件重新导入并完成测量后,导出才算完成,而不是导出器返回
FINISHED 时。先检查资产是否通过门槛,再使用预设导出,随后往返验证文件。此技能
基于 scenario-blender-expert(执行通道、交付门槛),并会导入其中的脚本,因此请将
这两个技能安装在同一目录下。如果此处提及的同级技能不在可用技能中,请让用户安装
(npx skills add scenario-labs/skills --skill <name>);如需无人值守运行,则根据工具架构继续操作并标明缺口。
工具包:scripts/bx_export.py。各引擎的相关事实及其来源:
references/engines.md。
快速参考
| 目标 | 预设 | 文件 | 引擎端 |
|---|---|---|---|
| Unity,静态网格 | unity | FBX | 导入默认设置 |
| Unity,角色 | unity_skeletal | FBX | 保持 Bake Axis Conversion 关闭 |
| Unreal Engine | unreal | FBX | Convert Scene Unit(转换为厘米) |
| Unreal Engine,角色 | unreal_skeletal | FBX | 一个根骨骼 |
| Godot 4 | godot | GLB | 导入默认设置;在停靠面板中生成 LOD |
| Roblox | roblox | FBX | 每个网格 20,000 个三角形 |
| three.js 和 Web | web | GLB、meshopt、WebP | MeshoptDecoder;不适用于 Godot |
| 任意 glTF 读取器 | gltf | GLB | |
| USD 管线 | usd | USDC | |
| Apple AR Quick Look | usdz | USDZ、2048 纹理 | |
| 3D 打印 | print | 毫米制 STL | 切片软件按毫米读取 |
Unity 和 Godot 预设已导入 Unity 6000.3 和 Godot 4.7.2 并完成测量;unreal、
unreal_skeletal 和 roblox 则依据 Epic 和 Roblox 的文档设置,且仅通过 Blender 往返验证。
测量结果见 references/engines.md。
流程
- 检查门槛。 运行
scenario-blender-expert中的bx_audit.deliverable(parts, profile),并修复所有 错误。留在对象上的缩放会作为节点变换传入引擎。 - 选择预设,参见表格。传入文件所需的每个对象:蒙皮网格及其 骨架、LOD 网格及其组,以及渲染网格旁的碰撞网格。
- 导出:
bxe.export(path, preset, objects, **overrides)。任何导出器关键字参数都会覆盖 预设,例如在roblox上设置bake_anim=True,以导出动画文件。结果会记录所用 设置。 - 往返验证:
bxe.round_trip(path, objects, preset=...)会在后台 Blender 中重新导入文件, 不会影响已打开的场景。它会按名称比较尺寸(1 mm)、三角形数量、变形骨骼、根 骨骼(预期为一个)、骨架缩放、形态键以及对象存储的每个动作。随后列出所有差异。 请逐项修复,或说明其为何符合预期。 - glTF 内容:
bxe.glb_summary(path)无需 Blender 即可列出extensions_required、形态目标、蒙皮、 动画片段和图像类型。若文件需要的扩展不受支持,加载器会拒绝该文件。 - 引擎检查: 将文件导入引擎并检查,可使用
scenario-unity-pipeline-automation、scenario-unreal-pipeline-automation或scenario-godot-pipeline-automation。
缩放、轴向和单位
- Blender 使用米制单位,Z 轴朝上,资产正面朝向 -Y。glTF 使用米制单位,Y 轴朝上(
export_yup)。FBX 将轴向存储为元数据;预设会将 -Z 设为前向、Y 设为上向。 - 将
scene.unit_settings.scale_length保持为 1.0。其他任何值都会缩放每次导出。 - 导出前应用对象缩放:
obj.data.transform(Matrix.Diagonal(obj.scale).to_4x4()),然后设置obj.scale = (1, 1, 1),这样引擎节点导入时的缩放为 1。 - FBX 缩放:
unity写入FBX_SCALE_ALL(Unity 读取的文件缩放为 1)。unreal保留FBX_SCALE_NONE(Unity 读取的文件缩放为 0.01,即以厘米为单位的文件)。roblox使用FBX_SCALE_UNITS,符合 Roblox 的导出要求。 - STL 不包含单位信息,切片软件会按毫米读取,因此
print会乘以 1000。
角色
- 将骨架与网格一同导出。
use_armature_deform_only会排除控制骨,因此所有变形骨都必须位于同一根骨骼之下的单个层级中。Unreal 的导入器会报告“Found multiple roots. The importer only supports one root per mesh.”(发现多个根骨。导入器仅支持每个网格有一个根骨。) - 所有预设都关闭了
add_leaf_bones。如果保持开启,每条骨骼链都会多出一根末端骨骼,从而破坏重定向。 unity_skeletal和unreal_skeletal会烘焙每个动作(bake_anim_use_all_actions),每个动作对应一个动画片段。Unity 会将每个片段命名为Armature|Action(实测:Rig|Wave),因此动作名称应与片段显示名称一致。glTF 会将每个动作作为一个以其自身名称命名的动画导出。roblox不导出动画。若要导出动画文件,请将bake_anim=True传给export()和round_trip(),后者也会比较动作。- 形状键会通过 FBX(混合形状)、glTF(变形目标,名称位于
extras.targetNames)和 USD 传递。构建 ARKit 或 viseme 集合属于scenario-blender-rigging的工作。 - Roblox:每个顶点最多有 4 个影响,骨骼必须冻结(缩放为 1、旋转为 0),根骨位于原点且不受任何影响,每个网格只有一个动画轨道。使用
max(len(v.groups) for v in obj.data.vertices)检查影响数。
LOD 和碰撞
bxe.lods(obj, ratios=(0.5, 0.25))会将网格重命名为Name_LOD0,并在名为Name的空对象下添加经过减面处理的Name_LOD1..n;该空对象会取代网格,位于其父级之下。仅适用于静态网格:带蒙皮的网格会被拒绝。Unity 会根据这些名称构建 LOD Group。Godot 会在导入时生成 LOD(Generate LODs)。Unreal 的文档说明为“Import LODs”,且所有 LOD 共用一个枢轴点。该组会作为普通 FBX Null 导出,Unreal 对其的导入情况尚未测量。bxe.collision(obj, engine, shape)会添加一个以导入器要求命名的碰撞网格:- Unreal:
UCX_Name_00(凸包)或UBX_Name_00(方盒),与模型一起导出到同一个 FBX。 - Godot:
convex(单个凸包)和box(边界框,即方盒碰撞体)使用Name-convcolonly;mesh(将网格作为三角网格,仅适用于静态物体)使用Name-colonly。 - Unity 和 Roblox:返回 None。碰撞体需在编辑器中设置。
- Unreal:
- 减面可能会破坏 UV 接缝和轮廓。导出前使用
bx_review检查每个 LOD。
批量转换
blender -b --factory-startup --python-exit-code 1 -P bx_export.py -- \
--batch /abs/in /abs/out --preset godot --profile game
对文件夹中的每个模型(GLB、glTF、FBX、OBJ、USD、STL、PLY):导入到空场景中,运行交付检查门,使用预设导出,重新导入并比较。它会将每个文件的检查门错误、大小和往返差异写入 /abs/out/report.json。单个文件失败不会中止整个文件夹:该文件会得到一个 failed 条目。两个输入文件同名时,输出名称会保留其格式(hero_fbx.glb、hero_glb.glb)。宣布批处理完成前,请先打开报告。
示例:将生成的 GLB 用于 Unity 和 Godot
import sys
sys.path.append("/abs/skills/scenario-blender-expert/scripts")
sys.path.append("/abs/skills/scenario-blender-export/scripts")
import bpy, bx_audit, bx_export as bxe
bpy.ops.wm.read_factory_settings(use_empty=True)
bpy.ops.import_scene.gltf(filepath="/abs/in/robot.glb")
parts = [o.name for o in bpy.context.scene.objects if o.type == "MESH"]
gate = bx_audit.deliverable(parts, profile="game")
print(gate["errors"]) # fix each one, then gate again until "pass" is True
bxe.export("/abs/out/robot.fbx", "unity", parts)
print(bxe.round_trip("/abs/out/robot.fbx", parts, preset="unity")["diffs"]) # []
bxe.export("/abs/out/robot.glb", "godot", parts)
print(bxe.glb_summary("/abs/out/robot.glb")["extensions_required"]) # []
生成的 GLB 通常会为每个部件包含一个对象,且所有对象共用资产的枢轴点。如果引擎需要为部件制作动画或替换部件,请保留为独立对象。若要制作单个静态道具,请将它们合并(选中这些部件后运行 bpy.ops.object.join),然后再次运行检查门。
常见错误
- 在
FINISHED时调用导出。导出器会成功处理引擎以 100 倍比例导入的文件,或未带皮肤的文件。 - 导出蒙皮网格时未包含其骨架,或导出骨架时未包含其网格。
- 设置 Bake Axis Conversion 或 Apply Transform 来移除骨架节点的旋转:两者都无法移除旋转,而且前者会让角色转向。
- 为 Godot 使用
web预设,或为没有相应解码器的加载器使用压缩 GLB。请先检查extensions_required。 - FBX 纹理仍为外部路径:预设会复制并嵌入纹理(
path_mode="COPY"、embed_textures=True),因此文件可独立使用。对于export()而言,没有扩展名的打包图像(如 GLB 导入后留下的图像)会先获得.jpg或.png文件名。尚未保存的图像(新建的烘焙目标)或修改过的图像会以像素打包副本的形式随文件一起导出(packed_unsaved_images)。 - 带纹理的 FBX 在 Unity 中显示为无纹理:默认导入会将嵌入的纹理保留在文件内。在 Materials 选项卡中使用 Extract Textures 将纹理提取到模型文件夹后,即可为其指定纹理。
- 使用 Blender 比例的 STL:一个 10 cm 的零件打印出来只有 0.1 mm。
- 导出的 LOD 未经检查:简化可能会导致细薄部件塌陷。