Unity MCP manage_editor 工具完全指南:编辑器状态控制、标签/图层管理与包部署实战
【免费下载链接】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
导读
manage_editor是 Unity MCP(MCP for Unity)核心工具组(core)中负责控制与查询 Unity 编辑器状态和设置的桥接工具,由 Python 服务端与 Unity 编辑器端共同实现。通过它,LLM 可以一键进入/退出播放模式、切换场景工具、增删 Tag 与 Layer、触发 MCPForUnity 包部署/回滚,以及执行 Undo/Redo,从而把“操作编辑器本身”纳入自动化工作流。读完本文你将掌握manage_editor的全部 14 个 action 的参数与返回值、底层调用链、以及如何与只读资源配合实现完整的编辑器自动化。
一、工具定位与 action 总览
根据 manage_editor 参考文档,该工具属于core组,模块名为services.tools.manage_editor。它同时提供只读与修改型两类 action:
- 只读(Read-only):
telemetry_status、telemetry_ping - 修改(Modifying):
play、pause、stop、set_active_tool、add_tag、remove_tag、add_layer、remove_layer、deploy_package、restore_package、undo、redo
注意:Prefab 编辑(打开/保存/关闭 Prefab Stage)不属于本工具职责,应使用
manage_prefabs。
参数表
| Name | Type | Required | Description |
|---|---|---|---|
action | Literal['telemetry_status', 'telemetry_ping', 'play', 'pause', 'stop', 'set_active_tool', 'add_tag', 'remove_tag', 'add_layer', 'remove_layer', 'deploy_package', 'restore_package', 'undo', 'redo'] | yes | 获取和更新 Unity 编辑器状态。deploy_package将配置的 MCPForUnity 源码复制到项目包目录(会触发重编译);restore_package从备份恢复最近一次部署;undo/redo执行编辑器撤销/重做。Prefab 编辑请使用manage_prefabs。 |
tool_name | str \| None | — | 设置活动工具时使用的工具名 |
tag_name | str \| None | — | 添加/删除标签时的标签名 |
layer_name | str \| None | — | 添加/删除图层时的图层名 |
返回值
返回一个包含 Unity 响应的dict,具体形状随 action 不同而变化。通用成功形态为{"success": true, "message": "...", "data": ...},失败时为{"success": false, "message": "..."}(详见下文源码解析)。
二、播放模式控制:play / pause / stop
三个 action 分别对应进入、暂停/恢复、退出播放模式,是自动化验证场景行为的最常用入口:
manage_editor(action="play") # 进入 Play Mode manage_editor(action="pause") # 暂停(再次调用则恢复) manage_editor(action="stop") # 退出 Play ModeUnity 端的实现位于 ManageEditor.cs,核心逻辑围绕EditorApplication.isPlaying与EditorApplication.isPaused:
- play:若
!EditorApplication.isPlaying则置为true并返回"Entered play mode.";已在播放模式则幂等地返回"Already in play mode."。 - pause:仅在播放模式下生效,将
isPaused取反,返回"Game paused."或"Game resumed.";非播放模式返回错误"Cannot pause/resume: Not in play mode."。 - stop:播放中则退出并返回
"Exited play mode.";否则返回"Already stopped (not in play mode)."。
从 manage_editor.py 可以看到,Python 服务端只负责参数组装与转发,真正执行动作的是 Unity 编辑器进程。
三、切换活动工具:set_active_tool
set_active_tool用于切换 Unity 场景视图的当前工具,等价于点击工具栏的 View/Move/Rotate/Scale 等按钮:
manage_editor(action="set_active_tool", tool_name="Move") # View | Move | Rotate | Scale | Rect | Transform在 ManageEditor.cs 中,tool_name会通过Enum.TryParse<Tool>(toolName, true, ...)大小写不敏感地解析为 Unity 内置Tool枚举。合法取值包括View、Move、Rotate、Scale、Rect、Transform;解析成功后通过UnityEditor.Tools.current = targetTool生效。需要注意两点边界:
- 若解析出的值属于
Tool.None、Tool.Custom或超出标准枚举范围,会返回错误"Cannot directly set tool to ...",因为这两者无法直接通过Tools.current切换; - 解析失败时提示可用的标准工具列表(View, Move, Rotate, Scale, Rect, Transform, Custom)。
四、标签管理:add_tag / remove_tag
用于向项目TagManager.asset添加或移除标签:
manage_editor(action="add_tag", tag_name="Enemy") manage_editor(action="remove_tag", tag_name="OldTag")Unity 端实现细节(ManageEditor.cs):
- add_tag:先通过
InternalEditorUtility.tags检查标签是否已存在(存在则报错),再调用InternalEditorUtility.AddTag(tagName),随后AssetDatabase.SaveAssets()强制持久化到磁盘。 - remove_tag:拒绝移除内置的
Untagged标签(Cannot remove the built-in 'Untagged' tag.);标签不存在时报Tag '...' does not exist.;移除成功后同样执行SaveAssets()。 - 空字符串或纯空白名称一律被拒绝。
配合只读资源使用:在调用前,可以通过mcpforunity://get_tags资源(实现见 Tags.cs)读取当前全部标签,避免重复添加或删除不存在的标签。
五、图层管理:add_layer / remove_layer
用于向ProjectSettings/TagManager.asset的 layers 数组添加或移除用户图层:
manage_editor(action="add_layer", layer_name="Projectiles") manage_editor(action="remove_layer", layer_name="OldLayer")Unity 端实现(ManageEditor.cs)通过SerializedObject直接操作ProjectSettings/TagManager.asset的layers属性,其关键约束体现了 Unity 图层机制本身:
- 用户图层区间:仅使用索引 8~31(
FirstUserLayerIndex = 8,TotalLayerCount = 32),前 8 层是 Unity 内置层,不可由用户修改。 - add_layer:先做全数组大小写不敏感的重名检查(重复则返回已存在的索引),再查找第一个空的用户图层槽位;若 8~31 全部被占用,返回
"No empty User Layer slots available (8-31 are full)."。写入后调用ApplyModifiedProperties()与AssetDatabase.SaveAssets()。 - remove_layer:仅在用户图层区间内按名称(忽略大小写)查找;找不到返回
"User layer '...' not found.";找到后将对应槽位字符串置空实现“删除”。 - 图层名称同样不允许为空或纯空白。
六、包部署与回滚:deploy_package / restore_package
这是本工具中风险最高也最实用的能力,专门服务于“LLM 驱动迭代”场景:将配置好的 MCPForUnity 源码目录复制到当前项目已安装的包目录中,立即触发重编译且无确认弹窗。
manage_editor(action="deploy_package") # 复制源码到已安装包位置并触发 AssetDatabase.Refresh manage_editor(action="restore_package") # 从上次部署的备份中恢复底层调用链
Unity 端入口在 ManageEditor.cs,分别调用
MCPServiceLocator.Deployment.DeployFromStoredSource()与RestoreLastBackup(),返回结果中携带source_path、target_path、backup_path。真正实现位于 PackageDeploymentService.cs:
- 源码路径来源:存储在
EditorPrefs的PackageDeploySourcePath键中(对应 EditorPrefKeys.cs),需先在 MCP for Unity 的 Advanced Settings 中设置。未设置时DeployFromStoredSource()返回"Select a MCPForUnity folder first."。 - 源码校验:目录必须同时包含
Editor和Runtime两个子文件夹,否则拒绝部署。 - 目标路径解析:优先使用
PackageInfo.FindForAssembly(...)获取已安装包的resolvedPath/assetPath,失败则回退到AssetPathUtility.GetMcpPackageRootPath()计算的包根目录。 - 部署过程:先在
Library/MCPForUnityDeployBackups/backup_<时间戳>创建目标目录的完整备份,再用FileUtil.DeleteFileOrDirectory+CopyFileOrDirectory覆盖目标的Editor、Runtime两个核心文件夹,最后AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate)触发重编译。 - 回滚:从
EditorPrefs读取最近一次备份与目标路径,将备份目录整体覆盖回目标路径并再次Refresh。
- 源码路径来源:存储在
部署工作流建议
按 tools-reference.md 中的说明,完整的自动化部署链路应为:
- 在编辑器 Advanced Settings 中设置 MCPForUnity 源码文件夹路径;
manage_editor(action="deploy_package")完成复制 + 备份 +Refresh;- 由于部署会触发脚本重编译,随后调用
refresh_unity(mode="if_dirty", wait_for_ready=True)等待编辑器重新编译完成,再进行后续操作。
七、撤销与重做:undo / redo
undo/redo直接调用 Unity 的 Undo 系统并返回受影响的撤销组名称,便于 LLM 感知操作上下文:
manage_editor(action="undo") manage_editor(action="redo")Unity 端实现(ManageEditor.cs):
- undo:先通过
Undo.GetCurrentGroupName()取得当前撤销组名,执行Undo.PerformUndo();若组名为空则提示"Undo performed (stack may be empty)."。返回数据包含undone_group(被撤销的组名)与next_group(撤销后的当前组名)。 - redo:执行
Undo.PerformRedo(),返回current_group。 - 播放模式警告:在播放模式下执行 undo/redo 时,返回消息会附加
"Warning: undo during play mode may have unexpected effects.",提醒调用方该操作在播放模式下的行为可能与预期不符。
八、只读遥测:telemetry_status / telemetry_ping
这两个 action 是唯二由 Python 服务端直接处理、不转发到 Unity的动作,属于诊断类接口:
manage_editor(action="telemetry_status") # 返回: {"success": true, "telemetry_enabled": true|false} manage_editor(action="telemetry_ping") # 返回: {"success": true, "message": "telemetry ping queued"}telemetry_status直接调用 telemetry.py 中的is_telemetry_enabled(),读取服务端遥测开关状态。telemetry_ping通过record_tool_usage("diagnostic_ping", True, 1.0, None)向遥测队列写入一条工具使用记录(异步、非阻塞),用于验证遥测链路是否可用。
从 test_manage_editor.py 的测试用例可以确认:这两个 action 由 Python 端就地处理,不会出现在转发给 Unity 的参数中(assert "params" not in mock_unity)。
九、服务端转发机制与参数裁剪
所有需要 Unity 执行的 action 都遵循统一的转发流程,其源码在 manage_editor.py:
- 通过
get_unity_instance_from_context(ctx)从请求上下文中获取当前活动的 Unity 实例(由中间件注入,支持多实例路由); - 组装
{action, toolName, tagName, layerName}参数字典,并剔除所有值为None的键——测试 test_undo_omits_none_params 专门验证了这一点; - 调用
send_with_unity_instance(async_send_command_with_retry, unity_instance, "manage_editor", params),经由统一的重试辅助函数发送命令; - 对响应做统一包装:成功时展开为
{"success": true, "message": ..., "data": ...};失败时原样返回结构化错误;任何异常兜底为{"success": false, "message": "Python error managing editor: ..."}。
UNITY_FORWARDED_ACTIONS参数化测试(test_manage_editor.py)逐一验证了play、pause、stop、set_active_tool、add_tag、remove_tag、add_layer、remove_layer、deploy_package、restore_package、undo、redo这 12 个动作都会以manage_editor工具名正确转发到 Unity。
另外,该工具在注册时通过ToolAnnotations标注了readOnlyHint=False、destructiveHint=True(见 manage_editor.py),向 MCP 客户端明确提示它属于破坏性/修改型工具,调用时应谨慎。
十、与只读资源的分工:何时用工具,何时用资源
manage_editor负责写操作,而读取编辑器状态应优先使用 MCP 资源,二者形成清晰分工:
| 需求 | 推荐方式 | 仓库依据 |
|---|---|---|
| 进入/退出/暂停播放模式 | manage_editor(action="play"/"stop"/"pause") | ManageEditor.cs |
| 切换场景工具 | manage_editor(action="set_active_tool", tool_name="Move") | ManageEditor.cs |
| 增删 Tag | manage_editor(action="add_tag"/"remove_tag") | ManageEditor.cs |
| 增删 Layer | manage_editor(action="add_layer"/"remove_layer") | ManageEditor.cs |
| 部署/回滚包 | manage_editor(action="deploy_package"/"restore_package") | PackageDeploymentService.cs |
| 撤销/重做 | manage_editor(action="undo"/"redo") | ManageEditor.cs |
| 查询当前 Tag 列表 | 资源mcpforunity://get_tags | Tags.cs |
| 查询编辑器动态状态(含活动工具、播放状态等) | 资源mcpforunity://get_editor_state | EditorState.cs、EditorStateCache.cs |
当 action 参数非法或缺失时,Unity 端会返回包含全部受支持 action 列表的错误信息,并在其中提示“Use MCP resources for reading editor state, project info, tags, layers, selection, windows, prefab stage, and active tool.”(见 ManageEditor.cs),即读取类操作请走资源通道。
十一、使用注意事项与最佳实践
- deploy_package 会触发重编译且无确认弹窗:部署会覆盖已安装包的
Editor/Runtime目录并立即刷新资源库。执行前请确认 Advanced Settings 中的源码路径指向正确的 MCPForUnity 目录,且目标与源目录不同(服务端会拒绝“源等于目标”的情况)。 - 部署后务必等待重编译完成:建议紧跟
refresh_unity(wait_for_ready=True),避免在编译中继续下发依赖新代码的命令。 - 备份即保险:每次
deploy_package都会在Library/MCPForUnityDeployBackups/下生成带时间戳的完整备份,restore_package依赖该备份路径(存储在EditorPrefs中)。若无备份可用,回滚会返回"No backup available to restore."。 - 修改前先查询:增删 Tag/Layer 前先读
get_tags或查看 TagManager 当前内容;图层仅能操作索引 8~31 的用户层,删除内置层会失败。 - 播放模式下谨慎 undo/redo:工具会主动附加警告,建议在编辑模式下执行撤销/重做。
- 参数大小写不敏感但校验严格:
tool_name解析忽略大小写;Tag/Layer 名称不允许空串,重复添加与删除不存在对象都会返回明确错误信息,LLM 可直接依据 message 字段进行纠偏。
小结
manage_editor将 Unity 编辑器“自身”变为可编程对象:播放控制、工具切换、Tag/Layer 维护、包部署回滚与撤销重做共 14 个 action,配合mcpforunity://get_editor_state、get_tags等只读资源,足以支撑“LLM 全自动驱动编辑器状态流转”的复杂工作流。其架构上采取 Python 服务端参数裁剪 + 实例路由、Unity 端EditorApplication/InternalEditorUtility/SerializedObject落地执行的清晰分层(详见 manage_editor.py 与 ManageEditor.cs),并有 test_manage_editor.py 对转发行为与参数裁剪做了完整回归保障。需要编辑 Prefab 时请转向manage_prefabs工具,完整的工具体系参考可见 tools-reference.md。
【免费下载链接】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),仅供参考