Unity MCPimport_model_file工具详解:将本地 FBX/OBJ/glTF 模型安全导入 Unity 项目
【免费下载链接】unity-mcpUnity MCP acts as a bridge between AI assistants and your Unity Editor. Give your LLM tools to manage assets, control scenes, edit scripts, and automate tasks within Unity.项目地址: https://gitcode.com/GitHub_Trending/un/unity-mcp
本文以 Unity MCP 仓库中的
import_model_file工具参考文档为骨架,结合 Python 服务端工具定义、C# 编辑器侧实现、导入管线与测试用例,完整讲解如何通过 AI 助手将磁盘上已有的 3D 模型文件(FBX/OBJ/GLB/glTF/zip)导入 Unity 项目,涵盖参数语义、动画类型、目标尺寸归一化、多文件 zip 处理与安全机制,读者读完后可熟练使用该工具并理解其底层调用链。
import_model_file是 Unity MCPasset_gen工具组中的一个关键工具,专门解决"本地已有模型文件"的导入场景——例如从 Blender、Maya 等 DCC 工具导出的 FBX/OBJ/glTF,或从 Sketchfab 下载的模型压缩包。与同组的import_model(从 Sketchfab 市场搜索并下载导入)不同,import_model_file不携带任何 API 密钥、不传输任何文件字节,是一个纯粹的"本地文件 → Unity 资产"桥接通道。
工具定位:DCC 无关、密钥无关的本地模型导入
根据 工具参考文档 的定义,该工具将磁盘上已存在的本地 3D 模型文件导入 Unity 项目:文件被复制到Assets/目录下,并交由 Unity 的模型导入管线处理(缩放归一化、材质设置;glTF 需要 glTFast 插件)。整个过程不携带 API 密钥、不跨桥传输文件字节。
在 Python 服务端,该工具由 Server/src/services/tools/import_model_file.py 定义,是一个"薄透传层"(thin pass-through):
@mcp_for_unity_tool( group="asset_gen", description=(...), annotations=ToolAnnotations(title="Import Model File", destructiveHint=False), ) async def import_model_file( ctx: Context, source_path: Annotated[str, "Path to the model file on disk (.fbx/.obj/.glb/.gltf/.zip)."], name: Annotated[str, "Base name for the imported asset."] | None = None, output_folder: Annotated[str, "Destination folder under Assets/ for the import."] | None = None, target_size: Annotated[float, "Normalize the largest dimension to this size (meters)."] | None = None, animation_type: Annotated[Literal["none", "generic", "humanoid", "legacy"], ...] | None = None, ) -> dict[str, Any]:服务端仅做三件事:从上下文解析目标 Unity 实例、剔除None参数、通过send_with_unity_instance把命令"import_model_file"连同参数(sourcePath/name/outputFolder/targetSize/animationType)发送给编辑器侧的 C# 实现。真正的工作全部在 Unity 编辑器内完成。
参数详解
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
source_path | str | 是 | 磁盘上模型文件的路径(.fbx/.obj/.glb/.gltf/.zip),支持绝对路径或Assets/相对路径 |
name | str \| None | 否 | 导入资产的基础名称;省略时取源文件名 |
output_folder | str \| None | 否 | Assets/下的目标文件夹;省略时使用默认输出目录 |
target_size | float \| None | 否 | 将模型最大维度归一化到该尺寸(单位:米) |
animation_type | Literal['none','generic','humanoid','legacy'] \| None | 否 | 仅 FBX/OBJ 有效:骨骼/动画导入模式 |
source_path:路径解析与扩展名校验
C# 侧 ImportModelFile.cs 对source_path做了两层处理:
- 路径解析:
ResolveSource将反斜杠统一替换为正斜杠;若路径以Assets或Assets/开头,则通过AssetGenPaths.ToAbsolute解析为项目绝对路径,否则视为磁盘绝对路径直接使用。 - 存在性与扩展名校验:文件不存在时返回
Source file not found: {source};扩展名不在白名单{ ".fbx", ".obj", ".glb", ".gltf", ".zip" }内时返回Unsupported model extension '...'。
name 与 output_folder:命名净化与目标目录
name为空时默认取Path.GetFileNameWithoutExtension(srcAbs)作为基础名;SanitizeName会把文件名非法字符替换为下划线,空名回退为"model"。output_folder缺省时使用AssetGenPrefs.OutputRoot + "/Imported";若该值无法解析到项目Assets/之下,则回退到默认根目录Assets/Generated/Imported(见 AssetGenPrefs.cs 中DefaultOutputRoot = "Assets/Generated")。- 目标目录下若已存在同名文件,自动追加
_1、_2序号避免覆盖(ImportModelFile.cs)。
target_size:模型尺寸归一化
target_size控制模型最大维度归一化。在 ModelImportPipeline.cs 的ApplyModelImporterSettings中,当AssetGenPrefs.AutoNormalize开启且TargetSize > 0时:
- 加载模型 GameObject,遍历所有
MeshFilter与SkinnedMeshRenderer,合并包围盒后取最大边长maxDim; - 计算
scale = target_size / maxDim,若与 1 偏差超过 1%,则关闭useFileScale并按比例调整globalScale(钳制在 0.0001~1,000,000 之间); - 调用
SaveAndReimport()使设置生效。
animation_type:骨骼与动画导入模式(FBX/OBJ 专属)
这是导致"带骨骼的 FBX 导入后零动画片段"最常见原因的开关。文档明确指出:
generic或humanoid:为带骨骼/动画的网格启用 Rig,使 Unity 暴露其 AnimationClips;none或省略:不导入 Rig——这正是带骨骼 FBX 导入后没有任何 clip 的常见原因;legacy:选择 Unity 旧版 Animation 系统(极少需要);- glTF/GLB 忽略该参数——glTFast 会自行导入动画。
底层映射见 ModelImportPipeline.cs 的ParseAnimationType,并由单元测试完整覆盖(ModelImportPipelineTests.cs):
| 输入 | 映射结果 |
|---|---|
generic/Generic | ModelImporterAnimationType.Generic |
humanoid/human | ModelImporterAnimationType.Human |
legacy/LEGACY(含空格) | ModelImporterAnimationType.Legacy |
none/ 空串 /null/ 任意非法值 | ModelImporterAnimationType.None |
返回值
工具返回包含 Unity 响应的dict,成功时形如:
{ "asset_path": "Assets/Generated/Imported/chair.fbx", "asset_guid": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }asset_path是导入后资产的 Assets 相对路径,asset_guid是其 GUID。若 Python 侧收到非 dict 结果,则返回{ "success": false, "message": str(result) };C# 侧导入失败时通过ErrorResponse返回错误信息(见 ImportModelFile.cs)。
端到端调用链
AI 助手 → import_model_file(source_path, name, output_folder, target_size, animation_type) [Python 服务端] → send_with_unity_instance("import_model_file", {sourcePath, name, outputFolder, targetSize, animationType}) → ImportModelFile.HandleCommand(JObject) [C# 编辑器侧] → 解析/校验路径 → StageUnderAssets 复制文件 → AssetDatabase.Refresh() → ModelImportPipeline.ImportInto(job, destRel) [共享导入管线] → 返回 { asset_path, asset_guid }C# 侧通过[McpForUnityTool("import_model_file", AutoRegister = false, Group = "asset_gen")]特性注册(ImportModelFile.cs),AutoRegister = false表示该工具由注册表显式挂载而非自动扫描注册。值得注意的是,工具刻意保持单一职责——只负责"把文件导入为资产",将模型放置到场景中由调用方负责。
多文件导出:zip 包的正确用法
对于多文件导出(文本.gltf配外部.bin,或.obj配同目录.mtl/贴图),必须打成 zip 再传入source_path——裸传.gltf/.obj只会复制主文件本身,侧边文件(sidecars)不会跟随。
zip 的处理流程在 ModelImportPipeline.cs 的ImportArchive中完成:
- 在 zip 同名(去
.zip后缀)目录下展开; - 通过
SafeZipExtractor解压,并配合扩展名白名单过滤——仅允许.gltf/.glb/.bin/.fbx/.obj/.mtl及常见贴图格式(.png/.jpg/.tga/.bmp/.exr/.ktx2/.dds等)写入Assets/; AssetDatabase.Refresh()+ 递归导入整个目录;- 调用
FindFirstModel在解压目录中查找第一个模型文件,优先 FBX/OBJ(内置导入器),其次 glTF(需要 glTFast); - 对找到的模型执行导入与导入器设置。
安全机制:Zip-Slip 防护与扩展名白名单
由于 zip 内容可能来自 Sketchfab 等不受信来源,SafeZipExtractor.cs 实现了两道防线:
- Zip-Slip 路径穿越防护:解压前检查每个条目名称,含
..或为绝对路径直接抛出Unsafe zip entry rejected;解压目标经Path.GetFullPath解析后必须仍位于目标目录前缀之内,越界条目抛出Unsafe zip entry escapes destination。 - 可执行内容隔离:白名单之外的条目(
.cs、.dll、.asmdef等)被直接跳过不写入,从机制上杜绝脚本/程序集在导入时被编译或加载进编辑器。
格式相关约束与前置条件
- FBX/OBJ:使用 Unity 内置
ModelImporter,支持animation_type与target_size归一化,导入前还会设置useFileScale = true与materialImportMode = ImportStandard(ModelImportPipeline.cs)。 - GLB/glTF:需要可选的glTFast包(可从 MCP for Unity → Dependencies 标签页安装)。若未安装,导入将失败并返回提示:
GLB import requires glTFast. Install it from the MCP for Unity → Dependencies tab, or choose FBX output.glTF 路径跳过animation_type(glTFast 自带动画导入),也跳过ApplyModelImporterSettings。 - 缺少 glTFast 时的失败路径由测试
Glb_WithoutGltfast_FailsWithActionableMessage验证(ModelImportPipelineTests.cs);文件必须位于Assets/之下(PathOutsideAssets_Fails)、路径不能为空(NullPath_Fails)等守卫同样有测试覆盖。
典型使用示例
示例 1:导入本地 FBX 并启用 Humanoid 动画
{ "source_path": "/Users/me/Downloads/character.fbx", "name": "player_char", "output_folder": "Assets/Characters", "animation_type": "humanoid" }示例 2:导入带贴图的 glTF(多文件打包)
{ "source_path": "C:/models/robot.zip", "name": "robot", "target_size": 2.0 }示例 3:仅导入静态网格(不创建 Rig)
{ "source_path": "Assets/Scratch/table.obj", "output_folder": "Assets/Props" }与其他工具的关系
import_model:从 Sketchfab 市场搜索/预览/下载/导入模型,携带用户自有的 Sketchfab 密钥(存放在编辑器安全存储中,同样不过桥),支持异步任务轮询(import_model.py)。generate_model:由 AI 提供商(Tripo/Meshy 等)生成模型。import_model_file与前两者的关键差异在于:输入是本地已存在的文件,且与import_model、generate_model最终都会汇入同一个ModelImportPipeline共享导入管线,因此缩放归一化、材质设置、动画类型、zip 安全解压等行为在各入口间保持一致。
总结
import_model_file是 Unity MCP 中连接"本地 DCC 工具产出"与"Unity 项目资产"的最直接通道:Python 侧保持薄透传、不携带密钥与字节,C# 侧完成路径解析、文件复制、共享管线导入与安全校验。正确理解animation_type对动画片段暴露的影响、target_size的归一化语义、以及多文件导出的 zip 打包约定,是高效使用该工具的关键;而对不受信 zip 的 Zip-Slip 防护与扩展名白名单机制,则为资产导入提供了可靠的安全边界。
【免费下载链接】unity-mcpUnity MCP acts as a bridge between AI assistants and your Unity Editor. Give your LLM tools to manage assets, control scenes, edit scripts, and automate tasks within Unity.项目地址: https://gitcode.com/GitHub_Trending/un/unity-mcp
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考