dsh-unity-bridge:把 Unity 编辑器接入 DSH

前言

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 网桥(编辑器进程内)

插件主要做三件事:

  1. 在 profile 里插入一条 @deepseek-ai/dsh-mcp-client(stdio)配置,指向 server/entry.mjs。
  2. 启动时由 server/entry.mjs 找到 Unity 项目,读取项目里的 ProjectSettings/McpUnitySettings.json 与 Library/McpUnity/bridge-token。
  3. 再加载该项目里 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 项目

按强度依次尝试,找不到可用桥接时才继续往下:

  1. MCP_UNITY_PROJECT 显式指定的项目根目录(最可靠,多项目建议用它)。
  2. MCP_UNITY_SETTINGS_PATH 指向的 ProjectSettings/McpUnitySettings.json 所在项目。
  3. Unity 编辑器日志(%LOCALAPPDATA%\Unity\Editor\Editor.log)里最近一次 -projectPath —— 只是线索,如果那个项目没装 mcp-unity 会继续扫描。
  4. 文件系统扫描(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

羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

小夜