前言¶
DeepSeek Harness(DSH)是一个以「一切皆插件」为理念的项目,开发者可以通过插件把各种外部服务或工具接进来,让模型在本地就能调用这些能力。在游戏开发场景里,Unity 编辑器本身是一个常用的工作台,但之前要把它接进 DSH,需要自己写不少桥接代码。
dsh-unity-bridge 是一个纯配置的 DSH bundle 插件,目标就是把 Unity 编辑器接进 DSH,让 DSH 里的模型可以调用 34 个 mcp__unity__* 工具(读写场景层级、增删改 GameObject / 组件、材质、预制体、场景、Play Mode、跑测试、看 Console、执行菜单项等),所有操作都发生在你正在运行的 Unity 编辑器里。
工作原理¶
DSH Agent 通过 MCP(stdio)连接到 dsh-unity-bridge,再由 bridge 把请求转发给 Unity 编辑器:
DSH Agent ──MCP(stdio)──> dsh-unity-bridge ──ws://127.0.0.1:8090/McpUnity──> Unity 编辑器
server/entry.mjs 项目里的 mcp-unity 网桥(编辑器进程内)
插件主要做三件事:
- 在 profile 里插入一条
@deepseek-ai/dsh-mcp-client(stdio)配置,指向server/entry.mjs。 - 启动时由
server/entry.mjs找到 Unity 项目,读取项目里的ProjectSettings/McpUnitySettings.json与Library/McpUnity/bridge-token。 - 再加载该项目里
com.gamelovers.mcp-unity自带的Server~/build/index.js,由它通过 WebSocket 连编辑器内的网桥。
因此:
- 不打包 server:协议永远跟随你项目里实际安装的那份 mcp-unity。
- 不复制令牌:令牌只在文件里,插件把路径和端口通过环境变量交给 server。
- 不改你的 Unity 项目:插件侧只读设置与令牌,不往项目目录写任何东西。
安装¶
安装前需要先在 Unity 项目里安装 com.gamelovers.mcp-unity 1.5.0+(包源:https://github.com/CoderGamester/mcp-unity.git),并保持编辑器打开(Tools > MCP Unity > Server Window 显示运行中)。首次启动会生成 Library/McpUnity/bridge-token。
DSH 侧安装:
Web 版:
```dsh plugin –profile web add git+https://github.com/pixelsoyo/dsh-unity-bridge.git
桌面版(使用内置 CLI,profile 换成 desktop):
```dsh plugin --profile desktop add git+https://github.com/pixelsoyo/dsh-unity-bridge.git
验证¶
新建会话,对 Agent 说「看一下当前场景层级」,它调用 mcp__unity__get_scenes_hierarchy 并返回真实节点树,就通了。
核心能力¶
- 零配置接入:装完即注册,不需要手写
cordis.patch.yml(要改行为再看配置项)。 - 34 个 Unity 工具:场景、GameObject、组件、材质、Prefab、菜单、测试、控制台日志等。
- 自动定位项目:支持显式路径 → settings 路径 → Unity 编辑器日志 → 文件系统扫描,多项目按「最近使用」排序。
- 握手挑正在跑的那个:所有候选并发探测
127.0.0.1与::1,用项目自己的令牌完成 WebSocket 握手,谁应答就用谁 —— 同时开着两个项目也不会连错。 - 不挑 Unity 版本:加载项目里那份 mcp-unity server,Unity 2022.3 到 Unity 6(及以后)都跟得上。
- 令牌不落地:只读文件路径做 Basic 握手,不复制、不打印。
- 三层超时:DSH 工具 180 秒、桥接请求 170 秒、Unity 内部默认 10 秒依次收窄,慢操作不会被莫名截断。
- 长跑不丢工具:重连预算 1000 次(约 8 小时),Unity 重启后自动恢复。
- 中文文档 + 排错表:日志里每条
[unity-mcp]提示都能在排错里对上。
环境要求¶
| 组件 | 要求 |
|---|---|
| DeepSeek Harness | 无硬性版本要求(当前验证于 0.2.x,含 rc);桌面端是当前主要验证环境 |
| Unity | 2022.3 及以上,含 Unity 6;上限取决于 mcp-unity 包本身 |
| mcp-unity(Unity 项目里) | com.gamelovers.mcp-unity 1.5.0+(1.5.0 起才有令牌握手) |
| 操作系统 | Windows 已实测;macOS / Linux 有对应日志路径回退,但未实测 |
为什么它不挑 Unity 版本(2022.3 及以上,Unity 6 及以后)¶
插件不打包 server,而是在启动时加载你 Unity 项目里那份 com.gamelovers.mcp-unity 自带的 server(Library/PackageCache/com.gamelovers.mcp-unity@*/Server~)。桥接协议永远和你实际安装的 Unity 包版本一致,Unity 升级或换项目都不需要改插件。同时也复用了包自己生成的 256 位桥接令牌,不复制、不硬编码密钥。
这里没有版本上限:插件代码里没有任何 Unity 版本判断,不认 ProjectVersion.txt 的版本号,也不依赖某个固定路径布局 —— 只要那个项目能装上 com.gamelovers.mcp-unity 1.5.0+ 并跑起来,插件就跟得上,Unity 6.x / 未来的 Unity 7 同理。真正的边界只有一条:mcp-unity 这个包本身支持到哪个 Unity 版本(它的 package.json 里写的是 "unity": "2022.3" 起)。插件只在 discovery.mjs 里对 mcp-unity 的版本做一次 < 1.5.0 的检查(低版本没有令牌握手,必然 401),这个检查跟 Unity 版本无关。
仓库结构¶
| 路径 | 作用 |
|---|---|
cordis.patch.yml |
插件清单:往 profile 里插入一条 @deepseek-ai/dsh-mcp-client(stdio),args 指向 server/entry.mjs |
server/entry.mjs |
stdio 启动器:定位项目 → 读设置与令牌 → 设环境变量 → 加载项目里的 mcp-unity server |
server/discovery.mjs |
项目发现(显式路径 / settings / Editor.log / 扫描)、锁文件定位、令牌与版本校验、formatHost |
server/probe.mjs |
并发 WebSocket 握手探测,挑出真正在监听的项目 |
locale/*.json |
插件页里的显示名与描述 |
test/run.mjs |
单测(npm test) |
tools/asar.mjs |
开发辅助:读 DSH 的 app.asar(不随包发布) |
工具一览(34 个)¶
| 分组 | 工具 |
|---|---|
| 场景 | get_scene_info、get_scenes_hierarchy、create_scene、load_scene、save_scene、unload_scene、delete_scene |
| GameObject | get_gameobject、select_gameobject、update_gameobject、update_component、duplicate_gameobject、delete_gameobject、reparent_gameobject、move_gameobject、rotate_gameobject、scale_gameobject、set_transform、add_asset_to_scene |
| 资产 | create_prefab、create_material、assign_material、modify_material、get_material_info |
| 编辑器 | get_play_mode_status、set_play_mode_status、recompile_scripts、run_tests、execute_menu_item、add_package |
| 日志 / 杂项 | get_console_logs、send_console_log、show_unity_dashboard、batch_execute |
安全边界(使用前请读)¶
装上这个插件等于把一个能改你项目的执行者接进来,边界如下:
| 项 | 行为 |
|---|---|
| 桥接令牌 | 只读取文件路径,值仅用于 Basic 握手头;不复制、不打印,日志里只有 Library/McpUnity/bridge-token 这个路径 |
| 网络 | 只连本机的 127.0.0.1 / [::1](未改 Host / UNITY_HOST 时),不向外发任何数据;Unity 侧 AllowRemoteConnections: false 是默认值 |
| 子进程环境 | 插件只额外加 4 个变量(MCP_UNITY_PROJECT、MCP_UNITY_PROBE、ELECTRON_RUN_AS_NODE、UNITY_REQUEST_TIMEOUT);其余父进程环境默认继承、按黑名单剔除:名字里含 KEY / PASSWORD / SECRET / TOKEN 的变量与所有 DSH_* 不会传进去(mcp-client 的 scrubbedParentEnv)。这不是白名单,凭据形状不同的变量仍会继承 |
| 执行项目内代码 | 启动时会 import 项目里 Library/PackageCache/com.gamelovers.mcp-unity@*/Server~/build/index.js,那是在 DSH 宿主 Node 进程里运行的第三方代码 —— 只对你信任的 Unity 项目启用本插件 |
| 写操作 | 模型可以增删改 GameObject/组件、创建/保存场景与预制体、切 Play Mode、跑测试 —— 会改并保存你的项目,请在版本控制下使用 |
| 执行代码类工具 | execute_menu_item 可触发任意菜单逻辑;add_package 能安装会执行编辑器代码的包,默认被 Unity 侧 AllowPackageInstallation: false 关闭 |
| 无人值守 | Unity 没开时 server 仍会启动,工具调用会重连失败;但不会在后台改文件 |
两点补充:
- 同一个 profile 里不要再启用另一个也用
serverName: unity的 bundle(例如旧版dsh-controlunity):重名时后加载的那条起不来,工具前缀也会互相覆盖。 - Unity 没开时工具调用不会立刻失败:请求会进 mcp-unity 的命令队列,约 60 秒后报
Command expired after 60000ms in queue(CommandQueue的defaultTimeout: 60000)。
它怎么找到你的 Unity 项目¶
按强度依次尝试,找不到可用桥接时才继续往下:
MCP_UNITY_PROJECT显式指定的项目根目录(最可靠,多项目建议用它)。MCP_UNITY_SETTINGS_PATH指向的ProjectSettings/McpUnitySettings.json所在项目。- Unity 编辑器日志(
%LOCALAPPDATA%\Unity\Editor\Editor.log)里最近一次-projectPath—— 只是线索,如果那个项目没装 mcp-unity 会继续扫描。 - 文件系统扫描(
MCP_UNITY_SEARCH_ROOTS,或默认的C:/D:/E:/F:/Unity*、%USERPROFILE%\Unity、Documents\Unity*,最多 3 层、4000 个目录项)。
候选项目按「最近使用」排序(token / settings / ProjectVersion 的修改时间),然后用项目自己的令牌 + mcp-unity: Basic 认证向 ws://<host>:<port>/McpUnity 发起一次 WebSocket 握手,谁回应就用谁 —— 所以同时开着两个 Unity 项目也能挑中真正在跑的那个,并顺手确认令牌有效。握手会自动区分 IPv4 127.0.0.1 与 IPv6 ::1(Windows 上 Unity 常常只监听 ::1,这是最常见的「端口是通的但连不上」原因)。
所有候选都会探测,且并发进行(每个候选同时试 127.0.0.1 与 ::1,默认 8 路并发):不会因为候选多了而漏掉真正在跑的项目,也不会把启动拖成十几秒;全部无应答时才回退到排序后的第一个候选。探测结果里的主机名会统一格式化后再交给 server —— IPv6 带方括号,这也是 UNITY_HOST 即使不经过探测也仍然合法的原因。
配置项¶
都在 cordis.patch.yml 的 env: 里(改完重载插件生效):
| 变量 | 默认 | 说明 |
|---|---|---|
MCP_UNITY_PROJECT |
空 = 自动 | 直接锁定项目根目录(含 Assets + ProjectSettings 的那层) |
MCP_UNITY_PROBE |
开 | 0 关闭握手探测(多项目时只按「最近使用」排序) |
MCP_UNITY_SEARCH_ROOTS |
自动 | 扫描起点,; 或 , 分隔 |
MCP_UNITY_SCAN |
关 | 1 强制每次都做文件系统扫描 |
MCP_UNITY_SETTINGS_PATH |
自动 | 直接指定项目的 ProjectSettings/McpUnitySettings.json |
MCP_UNITY_AUTH_TOKEN_PATH |
自动 | 直接指定令牌文件(默认 Library/McpUnity/bridge-token) |
UNITY_PORT |
项目设置 | 强制端口,必须和 Unity 实际监听的一致(见下节) |
UNITY_HOST |
自动 | 强制地址;一般不用填,握手探测会自动区分 127.0.0.1 / [::1] |
UNITY_REQUEST_TIMEOUT |
170(秒) |
server 等 Unity 回一次响应的超时上限;不设时 mcp-unity 默认 10 秒,编译 / 跑测试这类慢操作会被截断(见「超时」一节) |
端口/主机默认读项目里的 ProjectSettings/McpUnitySettings.json。启动时插件会把最终端口写进 UNITY_PORT,把主机名经 formatHost 规范化后写进 UNITY_HOST(localhost 不写,沿用默认值),保证 server 和探测结果一致;探测关闭时也一样格式化,所以 IPv6 不会漏方括号。
env: 里的空字符串表示「自动」。MCP_UNITY_PROJECT: '' 与删掉这一行等价。
端口(可以自定义)¶
端口是 Unity 编辑器在监听,不是插件监听的,所以真正的开关在 Unity 侧:
| 做法 | 怎么改 | 效果 |
|---|---|---|
| 推荐:改项目设置 | Unity → Tools > MCP Unity > Server Window 改 Port(写入 ProjectSettings/McpUnitySettings.json) |
插件下次启动自动读到新端口,插件本身不用动 |
| 强制:改插件 env | cordis.patch.yml 的 env: 里加 UNITY_PORT: '8091',重载插件 |
覆盖项目设置;Unity 没在 8091 上监听就会连不上(日志会明确提示) |
要点:
- 在 Unity 里改端口,插件文件一个都不用动:Connection Port 一变就会
SaveSettings()+RestartServer()(McpUnityEditorWindow.cs:93-106),新端口立刻写进ProjectSettings/McpUnitySettings.json并重新监听;插件下次启动照读。 - 但要「重载插件」:端口和令牌是 MCP server 进程启动时读一次并定格的,改完端口后需要重载插件才能生效。
超时(三个数字各管一段)¶
- DSH 工具超时:180 秒。
- 桥接请求超时:170 秒。
- Unity 内部默认:10 秒。
这三层超时依次收窄,避免编译 / 跑测试这类慢操作被莫名截断。
适用场景与注意¶
- 适合:需要在 DSH 中直接操作 Unity 场景、预制体、材质、控制台、菜单等,且希望尽量少配置的开发者。
- 注意:插件以当前 dsh 进程的权限运行;安装前应检查源码与许可证。同一个 profile 里不要同时启用多个使用
serverName: unity的 bundle,否则后加载的那条会起不来,工具前缀也会互相覆盖。
小结¶
dsh-unity-bridge 把 Unity 编辑器接入 DSH 的核心是「不打包 server,只加载项目里的 mcp-unity」,这样既保证了协议与 Unity 版本保持一致,也避免了在插件里硬编码端口或令牌。通过 stdio + WebSocket 的组合,模型可以在 DSH 里调用 34 个 Unity 工具,实现从场景操作到测试执行的全链路自动化。
插件主页:https://github.com/pixelsoyo/dsh-unity-bridge