# MCP for Unity 开发工具 | [English](README-DEV.md) | [简体中文](README-DEV-zh.md) | |---------------------------|------------------------------| 欢迎来到 MCP for Unity 开发环境!此目录包含简化 MCP for Unity 核心开发的工具和实用程序。 ## 🛠️ 开发环境搭建 ### 安装开发依赖 如果你想贡献代码或运行测试,需要使用 `uv` 安装开发依赖: ```bash # 进入 server 源码目录 cd Server # 以 editable 模式安装,并包含 dev 依赖 uv pip install -e ".[dev]" ``` 这会安装: - **运行时依赖**:`httpx`, `fastmcp`, `mcp`, `pydantic`, `tomli` - **开发依赖**:`pytest`, `pytest-asyncio` ### 运行测试 ```bash # 在 server 目录下 cd Server uv run pytest tests/ -v ``` 或者从仓库根目录执行: ```bash # 使用 server 目录中的 uv cd Server && uv run pytest tests/ -v ``` 只运行集成测试: ```bash uv run pytest tests/ -v -m integration ``` 只运行单元测试: ```bash uv run pytest tests/ -v -m unit ``` ## 🚀 可用的开发特性 ### ✅ 开发部署脚本 用于快速部署与测试 MCP for Unity 核心更改的工具。 **Development Mode Toggle**:内置 Unity 编辑器开发特性(现在作为 Advanced Setting 提供) **Hot Reload System**:无需重启 Unity 的实时更新(Roslyn Runtime_Compilation Custom Tools) **Plugin Development Kit**:用于创建 MCP for Unity 扩展的工具(Custom Tools) ### 🔄 即将推出 - **自动化测试套件**:为贡献提供更完整的测试框架 - **调试面板**:更高级的调试与监控工具 --- ## Advanced Settings(编辑器窗口) 使用 MCP for Unity 编辑器窗口(Window > MCP for Unity),在 Settings 选项卡内打开 **Advanced Settings**,可以在开发期间覆盖工具路径、切换 server 源、并将本地包部署到项目中。 ![Advanced Settings](./images/advanced-setting.png) - **UV/UVX Path Override**:当系统 PATH 解析不正确时,可在 UI 中指定 `uv`/`uvx` 可执行文件路径(例如使用自定义安装)。清空后会回退到自动发现。 - **Server Source Override**:为 Python server(`uvx --from mcp-for-unity`)设置本地文件夹或 git URL。清空后使用默认打包版本。 - **Dev Mode(强制全新安装 server)**:启用后,生成的 `uvx` 命令会在启动前添加 `--no-cache --refresh`。会更慢,但可避免在迭代 `Server/` 时误用旧缓存构建。 - **Local Package Deployment**:选择本地 `MCPForUnity` 文件夹(必须包含 `Editor/` 与 `Runtime/`),点击 **Deploy to Project** 后会将其复制到当前已安装的 package 路径(来自 `Packages/manifest.json` / Package Manager)。会在 `Library/MCPForUnityDeployBackups` 下保存带时间戳的备份,点击 **Restore Last Backup** 可回滚最近一次部署。 提示: - 部署/回滚后,Unity 会自动刷新脚本;若不确定,可重新打开 MCP window 并在 Advanced Settings 里确认目标路径标签。 - 保持 source 与 target 不要混用(不要把 source 指向已经安装的 `PackageCache` 文件夹)。 - 推荐使用被 gitignore 的工作目录进行快速迭代;部署流程只会复制 `Editor` 与 `Runtime`。 ## 快速切换 MCP 包源 从 unity-mcp 仓库运行,而不是从游戏的根目录。使用 `mcp_source.py` 可以在不同的 MCP for Unity 包源之间快速切换: **用法:** ```bash python mcp_source.py [--manifest /path/to/manifest.json] [--repo /path/to/unity-mcp] [--choice 1|2|3] ``` **选项:** - **1** 上游 main(CoplayDev/unity-mcp) - **2** 远程当前分支(origin + branch) - **3** 本地工作区(file: MCPForUnity) 切换后,打开 Package Manager 并 Refresh 以重新解析依赖。 ## Development Deployment Scripts 这些部署脚本帮助你快速测试 MCP for Unity 核心代码的更改。 ## Scripts ### `deploy-dev.bat` 将你的开发代码部署到实际安装位置以便测试。 **它会做什么:** 1. 将原始文件备份到一个带时间戳的文件夹 2. 将 Unity Bridge 代码复制到 Unity 的 package cache 3. 将 Python Server 代码复制到 MCP 安装目录 **用法:** 1. 运行 `deploy-dev.bat` 2. 输入 Unity package cache 路径(脚本会给出示例) 3. 输入 server 路径(或使用默认:`%LOCALAPPDATA%\Programs\UnityMCP\UnityMcpServer\src`) 4. 输入备份位置(或使用默认:`%USERPROFILE%\Desktop\unity-mcp-backup`) **注意:** Dev deploy 会跳过 `.venv`, `__pycache__`, `.pytest_cache`, `.mypy_cache`, `.git`;减少变动并避免复制虚拟环境。 ### `restore-dev.bat` 从备份恢复原始文件。 **它会做什么:** 1. 列出所有带时间戳的备份 2. 让你选择要恢复的备份 3. 同时恢复 Unity Bridge 与 Python Server 文件 ### `prune_tool_results.py` 将对话 JSON 中体积很大的 `tool_result` 内容压缩为简洁的一行摘要。 **用法:** ```bash python3 prune_tool_results.py < reports/claude-execution-output.json > reports/claude-execution-output.pruned.json ``` 脚本从 `stdin` 读取对话并将裁剪版本输出到 `stdout`,使日志更容易检查或存档。 这些默认策略可以显著降低 token 使用量,同时保留关键的信息。 ## 查找 Unity Package Cache 路径 Unity 会把 Git 包存储在一个“版本号或哈希”的文件夹下,例如: ``` X:\UnityProject\Library\PackageCache\com.coplaydev.unity-mcp@ ``` 示例(哈希): ``` X:\UnityProject\Library\PackageCache\com.coplaydev.unity-mcp@272123cfd97e ``` 可靠的查找方式: 1. 打开 Unity Package Manager 2. 选择 “MCP for Unity” package 3. 右键 package 并选择 “Show in Explorer” 4. Unity 会打开该项目实际使用的 cache 文件夹 注意:在近期版本中,Python server 的源码也会打包在该 package 内的 `Server` 目录下。这对本地测试或让 MCP client 直接指向打包 server 很有用。 ## Payload 大小与分页默认值(推荐) 某些 Unity 工具调用可能返回*非常大的* JSON payload(例如深层级场景、带完整序列化属性的组件)。为避免 MCP 响应过大、以及 Unity 卡死/崩溃,建议优先使用 **分页 + 先摘要后细节** 的读法,仅在需要时再拉取完整属性。 ### `manage_scene(action="get_hierarchy")` - **默认行为**:返回根 GameObject(无 `parent`)或指定 `parent` 的直接子节点的 **分页摘要**。不会内联完整递归子树。 - **分页参数**: - **`page_size`**:默认 **50**,限制 **1..500** - **`cursor`**:默认 **0** - **`next_cursor`**:当还有更多结果时返回 **字符串**;完成时为 `null` - **其他安全阀**: - **`max_nodes`**:默认 **1000**,限制 **1..5000** - **`include_transform`**:默认 **false** ### `manage_gameobject(action="get_components")` - **默认行为**:仅返回 **分页的组件元数据**(`typeName`, `instanceID`)。 - **分页参数**: - **`page_size`**:默认 **25**,限制 **1..200** - **`cursor`**:默认 **0** - **`max_components`**:默认 **50**,限制 **1..500** - **`next_cursor`**:当还有更多结果时返回 **字符串**;完成时为 `null` - **按需读取属性**: - **`include_properties`** 默认 **false** - 当 `include_properties=true` 时,会启用保守的响应大小预算(约 **~250KB** JSON 文本),返回条数可能少于 `page_size`;使用 `next_cursor` 继续。 ### 实用默认值(我们在 prompts/tests 中的推荐) - **Hierarchy roots**:从 `page_size=50` 开始,根据 `next_cursor` 继续(大场景通常 1–2 次调用)。 - **Children**:按 `parent` 分页,`page_size=10..50`(根据预期广度)。 - **Components**: - 先用 `include_properties=false` 且 `page_size=10..25` - 需要完整属性时,用 `include_properties=true` 且保持较小 `page_size`(例如 **3..10**)来控制峰值 payload。 ## MCP Bridge 压力测试 一个按需的压力测试工具会用多个并发客户端测试 MCP bridge,同时通过“立即脚本编辑”触发真实的脚本 reload(无需菜单调用)。 ### 脚本 - `tools/stress_mcp.py` ### 它做什么 - 对 MCP for Unity bridge 启动 N 个 TCP 客户端(默认端口从 `~/.unity-mcp/unity-mcp-status-*.json` 自动发现)。 - 发送轻量 framed `ping` 维持并发。 - 同时,使用 `manage_script.apply_text_edits` 对目标 C# 文件在 EOF 追加唯一标记注释,并设置: - `options.refresh = "immediate"` 来立即触发 import/compile(会引发 domain reload),以及 - 从当前文件内容计算 `precondition_sha256` 来避免漂移。 - 使用 EOF 插入避免头部/`using` guard 的编辑。 ### 用法(本地) ```bash # 推荐:使用测试项目中包含的大型脚本 python3 tools/stress_mcp.py \ --duration 60 \ --clients 8 \ --unity-file "TestProjects/UnityMCPTests/Assets/Scripts/LongUnityScriptClaudeTest.cs" ``` ### Flags - `--project` Unity 项目路径(默认自动检测到仓库自带的测试项目) - `--unity-file` 要编辑的 C# 文件(默认为长测试脚本) - `--clients` 并发客户端数量(默认 10) - `--duration` 运行秒数(默认 60) ### 预期结果 - Unity Editor 在 reload churn 下不崩溃 - 每次应用编辑后立即 reload(无需 `Assets/Refresh` 菜单调用) - 在 domain reload 期间可能会有少量短暂断线或失败调用;工具会重试并继续 - 最后输出 JSON 汇总,例如: - `{"port": 6400, "stats": {"pings": 28566, "applies": 69, "disconnects": 0, "errors": 0}}` ### 说明与排障 - Immediate vs debounced: - 工具设置 `options.refresh = "immediate"` 让每次改动都立刻编译。如果你只想测试 churn(不关心每次确认),可以改成 debounced 来减少中途失败。 - 需要 precondition: - 对较大文件,`apply_text_edits` 需要 `precondition_sha256`。工具会先读文件计算 SHA。 - 编辑位置: - 为避免头部 guards 或复杂范围,工具每轮都在 EOF 追加一行 marker。 - Read API: - bridge 当前支持 `manage_script.read` 用于读文件。可能会看到弃用提示;对该内部工具无影响。 - 瞬时失败: - 偶尔出现 `apply_errors` 往往意味着连接在回包时发生 reload。通常编辑仍然已应用;循环会继续下一轮。 ### CI 指导 - 由于 Unity/editor 依赖与运行时波动,不建议把它放进默认 PR CI。 - 可选择作为手动 workflow 或 nightly job 在支持 Unity 的 runner 上运行。 ## CI 测试工作流(GitHub Actions) 我们提供 CI 作业来对 Unity 测试项目运行自然语言编辑套件:它会启动 headless Unity 容器并通过 MCP bridge 连接。要在 fork 上运行,你需要以下 GitHub Secrets:`ANTHROPIC_API_KEY` 以及 Unity 凭据(通常为 `UNITY_EMAIL` + `UNITY_PASSWORD` 或 `UNITY_LICENSE` / `UNITY_SERIAL`)。这些会在日志中被脱敏,因此不会泄露。 ***如何运行*** - 触发:在 GitHub Actions 中手动触发 `workflow dispatch`(`Claude NL/T Full Suite (Unity live)`)。 - 镜像:`UNITY_IMAGE`(UnityCI)使用 tag 拉取;作业会在运行时解析 digest。日志会被清理。 - 执行:单次执行,每个测试生成一个片段(严格:每个文件只允许一个 ``)。若任何片段只是裸 ID,会被占位符 guard 快速判失败。暂存目录(`reports/_staging`)会被提升到 `reports/` 以减少部分写入。 - 报告:JUnit 输出到 `reports/junit-nl-suite.xml`,Markdown 输出到 `reports/junit-nl-suite.md`。 - 发布:JUnit 会被规范化为 `reports/junit-for-actions.xml` 并发布;Artifacts 会上传 `reports/` 下的全部文件。 ### 测试目标脚本 - 仓库包含一个很长且独立的 C# 脚本,用于验证大文件编辑与窗口读取: - `TestProjects/UnityMCPTests/Assets/Scripts/LongUnityScriptClaudeTest.cs` 本地与 CI 都建议用它来测试多编辑批次、anchor insert、windowed read 等。 ### 调整 tests / prompts - 修改 `.claude/prompts/nl-unity-suite-t.md` 来调整 NL/T 步骤。遵循约定:每个测试在 `reports/_results.xml` 下生成一个 XML 片段,且每个片段恰好包含一个 ``,其 `name` 必须以 test ID 开头。不要包含 prologue/epilogue 或代码围栏。 - 保持改动最小、可回滚,并给出简洁证据。 ### 运行套件 1) 推送你的分支,然后在 Actions 标签页手动运行 workflow。 2) 作业把 reports 写入 `reports/` 并上传 artifacts。 3) “JUnit Test Report” check 会汇总结果;打开 Job Summary 查看完整 Markdown。 ### 查看结果 - Job Summary:Actions 中的内联 Markdown 汇总 - Check:“JUnit Test Report” - Artifacts:`claude-nl-suite-artifacts`,包含 XML 与 MD ### MCP 连接调试 - 在 MCP for Unity 窗口(Editor 内)*启用 debug logs*,可以看到连接状态、auto-setup 结果与 MCP client 路径,包括: - bridge 启动/端口、client 连接、strict framing 协商、解析后的 frame - auto-config 路径检测(Windows/macOS/Linux)、uv/claude 解析与错误提示 - CI 中如启动失败,作业会 tail Unity 日志(serial/license/password/token 已脱敏),并打印 socket/status JSON 诊断。 ## Workflow 1. **修改** 此目录中的源码 2. **Deploy** 使用 `deploy-dev.bat` 3. **在 Unity 中测试**(先重启 Unity Editor) 4. **迭代** - 按需重复 1-3 5. **Restore** 完成后用 `restore-dev.bat` 恢复原始文件 ## Troubleshooting ### 运行 .bat 时出现 "Path not found" - 确认 Unity package cache 路径正确 - 确认 MCP for Unity package 已安装 - 确认 server 已通过 MCP client 安装 ### 出现 "Permission denied" - 用管理员权限运行 cmd - 部署前关闭 Unity Editor - 部署前关闭所有 MCP client ### 出现 "Backup not found" - 先运行 `deploy-dev.bat` 生成初始备份 - 检查备份目录权限 - 确认备份路径正确 ### Windows uv 路径问题 - 在 Windows 上测试 GUI client 时,优先使用 WinGet Links 下的 `uv.exe`;若存在多个 `uv.exe`,可用 “Choose `uv` Install Location” 固定 Links shim。 ### Unity 退到后台时 Domain Reload Tests 卡住 在测试过程中触发脚本编译(例如 `DomainReloadResilienceTests`)时,如果 Unity 不是前台窗口,测试可能会卡住。这是操作系统层面的限制——macOS 会限制后台应用的主线程,从而阻止编译完成。 **Workarounds:** - 运行 domain reload tests 时保持 Unity 在前台 - 在测试套件最开始运行它们(在 Unity 被切到后台之前) - 使用 `[Explicit]` 属性将其从默认运行中排除 **注意:** MCP workflow 本身不受影响——socket 消息会给 Unity 提供外部刺激,使其即使在后台也保持响应。该限制主要影响 Unity 内部测试协程的等待。