关于 unity-cli
unity-cli 是一个说明性模块,介绍在 Unity Editor 关闭时通过本地 Shell 操作 Unity CLI 的流程。它面向 Unity 开发者,可用于启动项目、运行测试和批处理任务,以及无头构建;具体操作受项目配置和功能开关限制。
主要功能
- 01启动或检查 Unity Editor 实例
- 02启动时传入命令行参数
- 03运行测试并输出 NUnit XML
- 04执行一次性批处理任务
- 05通过命令行构建项目
适用场景
- 01在 CI 中运行回归测试
- 02Editor 关闭时执行自定义批处理方法
- 03打开项目并直接进入指定场景
- 04启用相应功能后执行无头构建
MCP 相关
此模块不提供 REST 技能,而是说明如何在本地运行 Shell 命令,并在 Editor 关闭时补充基于 MCP 的 Editor 工作流。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ besty0728/ unity-skills --skill unity-cli安装后在 Claude Code 中输入/unity-cli确认已加载。
详细介绍
**在调用此模块中的任何技能之前:**如果你准备根据技能名称或描述猜测参数来调用技能,请停下——先阅读此文件(或通过
GET /skills/recommend?includeSchema=true获取其架构)。如果你已从 recommend/schema 获得参数定义,则可以直接进行 dryRun。
Unity CLI(说明)
**说明模块——无 REST 技能。**此处的所有命令都在用户机器上的你的 Shell 中运行,而不是通过 REST 服务器运行。这正是它们的用途:即使 Unity Editor 已关闭,也能正常运行。
使用前提——请先阅读
使用以下任何内容之前,请检查绑定配置:
<projectRoot>/Library/UnitySkills/cli_config.json
- 文件缺失、不可读或
enabled: false→ **此项目未启用 Unity CLI。请完全忽略此模块。**不要在用户未提出要求时建议安装 CLI;用户可通过Window > UnitySkills → AI Config → Unity CLI Setup…主动启用。 enabled: true→ 使用cliPath作为可执行文件(它可能不在你的 PATH 中)。遵循features中各功能的开关:
{
"schemaVersion": 1,
"enabled": true,
"cliPath": "/Users/me/.local/bin/unity",
"cliVersion": "1.0.0-beta.5",
"projectPath": "/path/to/Project",
"editorVersion": "6000.0.32f1",
"boundAt": "2026-07-26T09:00:00Z",
"features": { "coldStart": true, "openArgs": true, "cliTest": true, "cliRun": false, "cliBuild": false }
}
较旧插件版本写入的配置可能缺少 cliRun / cliBuild 键——对于这两个键,缺少键表示关闭(前三个键保持原有语义)。新绑定时,这两项也默认关闭;用户可在面板中为各项目启用。
全局注册表(~/.unity_skills/registry.json)也会记录每个运行实例的 cliBound / cliPath——仅将其用于存活状态检查,绝不能用作授权依据:授权某个项目使用 CLI 的唯一依据,是该项目自身的 cli_config.json。即使某个项目显示在注册表中,也不要冷启动任何尚未读取其自身配置的项目。另请注意,配置中的 projectPath 是绑定时的快照——实际找到配置文件所在的目录才是权威路径(辅助函数 get_cli_config() 已会重写该值);如果存储路径与实际项目根目录不同,绝不要打开存储的路径。
Unity CLI 仍处于实验阶段(beta),其命令接口会随版本变化——本文档已针对
1.0.0-beta.9验证(beta.7 发布当天即被撤回)。配置中的cliVersion仅是绑定时的快照;已安装的二进制文件版本可能更高。使用近期语义有变的命令前,请先阅读<cliPath> --version和<cliPath> <command> --help——对于磁盘上的二进制文件,--help始终是最终依据。beta9+ 中的<cliPath> skill show --list/--path <file>会只读打印 Unity 自带的 Agent 技能(离线,总计约 44k 个 token——每次读取一个文件)——这是第二参考资料,不是授权依据;本模块的使用前提和禁止事项仍然适用。如果命令意外报错,请先运行<cliPath> doctor --format json(环境快照;使用--tail <n>查看更多日志),并在重试前再次检查--help。绝不要通过修改服务器或配置来绕过 CLI 的异常行为。
1. 冷启动 / 生命周期(features.coldStart)
REST 永远无法提供的一项能力:在编辑器未运行时启动编辑器。
<cliPath> status --format json # any editor instances running?
<cliPath> open "<projectPath>" --args -unityskills-coldstart
冷启动时始终传入 --args -unityskills-coldstart:UnitySkills 插件会在编辑器启动时检测此标记,并强制为本次会话启动 REST 服务,即使用户关闭了自动启动偏好设置。没有此标记,就只能依赖用户保存的偏好设置。此标记在每个编辑器会话中只使用一次——它绝不会覆盖会话中途的手动停止操作。
预检——只读,无需启用功能开关。 open / test / run / build 都会根据项目的 ProjectVersion.txt 确定编辑器。会话中首次启动 CLI 前,运行以下检查;这些检查都不会修改项目:
<cliPath> editors -i --format json # all versions: is the bound editorVersion installed?
<cliPath> doctor --ci --format json # beta6+: exit 6 = definitive blocker, 7 = retryable
<cliPath> projects verify "<projectPath>" --format json # beta6+: exit 6 = errors, 0 = clean or warnings only
doctor --ci(在项目根目录运行)会检查许可证、项目的编辑器、磁盘空间和 Unity 服务;根据errors[].code(LICENSE_NONE、EDITOR_NOT_INSTALLED、DISK_SPACE_LOW、NETWORK_UNREACHABLE)采取相应操作:6→ 停止并报告,7→ 重试几次,然后告知用户。普通的doctor始终以0退出。macOS 上的 beta6–8 可能会卡在钥匙串提示处——请用 shell 超时限制其运行时间。projects verify无需 Editor、许可证或网络,只会检测:META_MISSING/META_ORPHAN/GUID_DUPLICATE/CONFLICT_MARKERS/MANIFEST_INVALID;若出现这些问题,则以6退出——报告问题,切勿手动修复;警告(通过--expect-editor <version>检测到的PATH_UNVERIFIABLE、EDITOR_VERSION_DRIFT)以0退出,除非使用了--strict。
如果未安装编辑器,请停止并告知用户——绝不要运行 install 或传入 --allow-install(参见“禁止操作”)。
启动后,轮询 UnitySkills REST 服务,直到服务就绪(首次导入 / 编译可能需要几分钟):
from unity_skills import wait_for_health
health = wait_for_health(timeout=600) # polls /health on ports 8090-8100
beta9+:如果 Editor 在 CLI 的短暂监视窗口内退出,open 会以 6(OPEN_EDITOR_EXITED)退出——应立即报告,而不是等待 wait_for_health。只有该窗口内的退出会被检测到:Editor 之后退出时不会被发现;旧版二进制文件则无论如何都会以 0 退出,因此 wait_for_health 超时仍是实际的故障信号。
存活状态排查——优先于盲目重试。 当 REST 无法连接时,先确认 Editor 是否实际正在运行,再决定是否冷启动:
- 先读取项目自己的
cli_config.json。 只有文件存在且enabled: true时才继续。 - 检查 UnitySkills 注册表:读取
~/.unity_skills/registry.json,找到path等于项目根目录的条目,然后检查其pid(ps -p <pid>/ Windowstasklist)。PID 存活 → 编辑器正在运行,但正忙(Domain Reload / 导入)→ 继续按常规方式等待 REST 并重试;不要冷启动。 - 通过 CLI 进程列表交叉确认:
<cliPath> editors running --format json --non-interactive会列出 CLI 能看到的 Editor 实例。这可用于确认,但只能看到 CLI 后端识别的实例。 - 检查
Library/UnityLockfile。 锁文件被占用,意味着此项目中有 Editor 实例处于打开状态,即使注册表中没有相应条目也是如此。 <cliPath> status只是辅助信息,不具权威性:它仅反映 Unity Pipeline 连接状态。表格为空 / 非零退出码并不表示编辑器已关闭——实践中已验证:未安装 Pipeline 包的运行中编辑器不会显示任何内容。
如果 PID、CLI 进程列表或锁文件表明已有 Editor 在此项目中运行,不要运行 open、run 或 build——Unity 不允许同一项目同时启动第二个实例。只有上述检查均未发现此项目中有运行中的 Editor 时,才应使用 open 冷启动,然后运行 wait_for_health。
2. 使用参数启动(features.openArgs)
<cliPath> open "<projectPath>" --args -openscene "Assets/Scenes/Main.unity"
--args 之后的所有内容都会作为标准命令行参数传递给 Unity Editor。可用于进入已知状态(特定场景、自定义 -executeMethod)。此操作仅在启动时有效——对于已运行的编辑器,请改用 REST scene_load。
3. 无头测试(features.cliTest)
<cliPath> test "<projectPath>" --mode EditMode --filter <pattern> --output test-results.xml --timeout 1800
--mode <EditMode|PlayMode>— 省略时使用编辑器的默认测试平台;使用两次独立调用覆盖两种模式。--filter <pattern>— 仅运行名称匹配的测试。--output <path>— NUnit XML 报告(默认值为test-results.xml)。在 CI 中,继续使用此文件获取测试结果。- 仅限 CI 的参数 —
test --help可能会列出报告/覆盖率标志(beta4+:--report-format nunit,junit、--junit-output、--coverage*),以及 beta6+ 的--shard N/M、--retries N(仅重新运行失败的测试,每次尝试的超时时间由--timeout指定,在test-results.retries.json中列出不稳定测试;始终无法通过的测试仍会以8退出)和--rerun-failed(从--output读取失败测试集合,并写入test-results.rerun.xml)。beta9+ 的--affected --since <ref>仅运行更改可能影响到的测试(这只是近似结果,会写入test-results.affected.xml)——在信任它之前,先运行--affected-compare,测量其漏报率。各选择器互斥。仅当当前二进制文件的test --help中列出某个参数时才使用;切勿猜测参数名称。 --timeout <seconds>(环境变量UNITY_TEST_TIMEOUT)— N 秒后终止 Unity 进程;默认禁用,无人值守运行时务必设置超时时间。- 额外的编辑器参数通过
--传递,例如-- -nographics。 - 退出代码:
0表示全部通过(包括--retries使不稳定测试通过的情况——仍会报告不稳定性)。beta6+:8表示测试失败(errors[0].code为TESTS_FAILED);6表示没有判定结果——编译错误、许可证问题或 Editor 崩溃(TEST_RUN_ERROR)、--timeout超时(TEST_TIMED_OUT)。beta3–5:6涵盖以上两种情况——请查看 XML 加以区分。Unity 服务在 CLI 重试后仍无法访问时返回7;收到 SIGINT 时返回130;收到 SIGTERM 时返回143;任何其他非零值都表示命令本身失败——请检查 stderr、JSON 封装和errors[].code,不要只查看 XML。仅在必要时重试6/7;切勿重试8。
路由规则:
- 交互式迭代(编辑器已运行,可快速反馈少量测试结果)→ 使用 REST
test_*技能。 - 完整回归/CI 风格运行,或编辑器已关闭 → 使用
unity test(无头模式,输出 NUnit XML)。不要对编辑器仍在运行的项目执行unity test。
4. 批处理运行(features.cliRun)
仅对已绑定的项目执行一次性批处理自动化,且编辑器必须关闭——这是 REST(编辑器已打开,可交互)和冷启动(启动并持续提供服务)之间的第三种生命周期选项:
<cliPath> run "<projectPath>" --timeout 1800 -- -executeMethod Your.Static.Method -quit
--后的所有内容都会作为标准命令行参数转发给 Unity Editor;典型用法是-executeMethod <static method>加-quit(资源重新导入、批处理修复、自定义流水线)。- 将编辑器日志流式输出到 stdout,并返回编辑器的退出代码——非零表示批处理运行失败。beta5+ 会将 Editor 崩溃报告为
stopped with signal SIG…(见 §6)——这表示 Editor 崩溃,而非业务逻辑失败。 --timeout <seconds>(环境变量UNITY_RUN_TIMEOUT)— 默认禁用;务必设置超时时间,否则批处理 Editor 卡住时会让 shell 永远阻塞。- 路由:编辑器已运行 → 使用 REST 技能,切勿使用
run(Unity 拒绝在同一项目上启动第二个实例——与冷启动遵循相同的Library/UnityLockfile规则)。编辑器已关闭,且需要持久会话 → 冷启动。编辑器已关闭,且只需执行一次性任务 → 使用run。 run --command <name>用于驱动 Unity Pipeline 包命令——不属于此工作流(见「禁止事项」)。
5. 无头构建(features.cliBuild)
默认情况下,cliBuild 处于关闭状态。用户启用后,根据已安装的 CLI 版本、Unity Editor 版本、目标平台以及是否存在 Build Profile,选择构建路径:
路径 1 — Unity 6 Build Profile(beta4+)
<cliPath> build "<projectPath>" --profile "Windows" --output-path ./Builds/win64
--profile接受 Build Profile 资源路径或 Build Profile 窗口中显示的配置文件名称。- 需要 Unity 6(
6000.x)和已配置的 Build Profile。
路径 2 — 内置桌面构建(beta4+)
<cliPath> build "<projectPath>" --target StandaloneWindows64 --output-path ./Builds/win64
- 仍然需要
--target。 - 对于桌面目标,从 beta4 开始,
--execute-method为可选项;提供--output-path时,CLI 可以驱动内置桌面构建。
路径 3 — 自定义 C# 构建方法(所有版本均适用;移动端/WebGL 必需)
<cliPath> build "<projectPath>" --target Android --execute-method Builder.PerformBuild --output-path ./Builds/android
- 如果提供了
--execute-method,它仍然兼容且优先级更高;Android、iOS、WebGL 或已有自定义构建管线的项目应使用它。 --output-path会作为-buildOutput转发给 Unity;执行方法本身负责读取它。- 如果项目中尚无静态构建方法,请告知用户,而不要擅自将其写入项目。
通用构建标志
- 默认情况下,构建日志的末尾会输出到 stdout(使用
--no-tail可禁用);完整日志会写入<project>/Logs/build-<target>-<timestamp>.log,除非通过--log-file指定其他路径。beta6+ 还会在构建产物旁写入<output>.provenance.json,记录实际构建内容,包括构建失败时的情况(使用--no-provenance可跳过)。 --timeout <seconds>(环境变量UNITY_BUILD_TIMEOUT,beta6+)——中止构建并以6退出;默认禁用。无人值守构建时务必设置超时。beta6+ 的 json/ndjson 也会包含心跳帧(已用时间,以及日志上次增长至今的秒数;即使使用--quiet也会包含):Editor 停滞时,增长的是间隔,而不是静默。- 脏工作区保护:存在未提交更改时,
build会拒绝运行。这项保护是有意设置的——只有用户明确要求时才传入--allow-dirty-build。 --versioning-strategy <semantic|tag|custom|none>(默认none)根据 git 标签/历史记录为构建版本添加标记;--build-version仅在使用custom时生效。- Android:提供
--android-export-type <apk|aab|android-studio-project>以及密钥库/签名标志,但命令行中的密钥会泄露到 shell 历史记录和 CI 日志中——让用户自行处理签名;绝不要让用户将密钥库密码粘贴到 shell 命令中。 - 生命周期规则与
run相同:仅限已绑定的项目,Editor 必须关闭;Editor 再次启动后,所有常规操作都必须通过 REST 进行。 - 退出代码/信号:
0表示成功;6表示构建失败、--timeout超时(beta6+)或 Editor 异常退出;7表示重试后仍无法连接 Unity 服务;130表示 SIGINT;143表示 SIGTERM。beta5+ 会将 Editor 崩溃报告为stopped with signal SIG…(见 §6)——应将其与BUILD_FAILED区分处理。
6. 自动化约定(所有命令)
- 结构化输出:
--format <human|json|tsv|ndjson>(环境变量UNITY_FORMAT);--json是--format json的简写。将 stdout 重定向到管道时,默认格式会静默切换为 TSV——这也是始终显式传入--format json的另一个理由。JSON 响应使用标准封装{success, command, data, errors, warnings};ndjson会为长时间运行的命令流式输出进度事件。 - 非交互模式:
--non-interactive(环境变量UNITY_NON_INTERACTIVE)会将提示转换为硬错误,避免 shell 一直挂起;搭配--quiet(环境变量UNITY_QUIET)和--no-banner(环境变量UNITY_NO_BANNER),即可获得干净的机器输出。 - 脚本调用的推荐环境变量(仅供参考,效果等同于上述标志):
UNITY_NON_INTERACTIVE=1— 禁用交互提示。UNITY_FORMAT=json— 默认输出格式;同时设置时,命令行--format优先。UNITY_NO_PAGER=1— 长输出不分页(beta4+ 会在交互式终端中使用分页器)。UNITY_NO_CRASH_REPORT=1— 选择退出通过 Sentry 进行的匿名崩溃报告(beta3+)。UNITY_NO_CLI_INVOKED_TELEMETRY=1— 选择退出每次运行都会发送的使用情况 ping(beta9+;与分析数据的选择加入机制相互独立)。
- 错误和退出代码:数据写入 stdout,错误和诊断信息写入 stderr(JSON 模式下的错误也一样)。务必同时查看 JSON 封装、
errors[].code和 stderr——不要只依赖单个退出代码。
| 退出代码 | 含义 |
|---|---|
0 | 成功。 |
1 | 通用错误——查看 stderr / JSON errors。 |
2 | 用法或参数错误(命令错误、缺少必需标志)。 |
3 | 身份验证或授权失败。 |
4 | 缺少必需配置。 |
6 | 主要操作失败或未得出结论——构建失败、--timeout 超时(beta6+)、Editor 异常退出或崩溃、test 未得出结论(beta6+;beta3–5 也会将测试失败归入此代码)、doctor --ci 确认存在阻塞项、projects verify 出错、open 的监视窗口内 Editor 退出(beta9+,OPEN_EDITOR_EXITED)。 |
7 | CLI 重试后仍无法访问 Unity 服务,或 doctor --ci 未得出结论(beta6+);最多重试有限次数。6 表示终止错误,7 可能是暂时性错误。 |
8 | 测试失败(test,beta6+,TESTS_FAILED);绝不要重试。beta3–5 会将此类错误报告为 6。 |
130 | 用户取消(SIGINT / Ctrl+C)。 |
143 | 被 SIGTERM 终止。 |
- NDJSON 流式输出:要实时查看进度,请使用
--format ndjson。从 beta4 起,流末尾会以终止的type=result帧结束——应使用最后一个{"type":"result","success":...}帧作为最终状态,绝不要使用较早的进度帧或 stderr 行;beta3 不会输出结果帧,此时应根据退出代码和 stderr 判断。 - 信号导致的崩溃(beta5+):
build/test/run会将 Editor 崩溃报告为stopped with signal SIGSEGV/SIGILL/SIGTRAP/SIGFPE/SIGBUS。应将此类崩溃与业务失败(beta6+ 的TESTS_FAILED/ 此前版本的TEST_FAILED、BUILD_FAILED)以及 CLI 侧失败(参数、配置、网络、身份验证)区分开。 --verbose会添加完整错误详情和堆栈跟踪——向用户报告 CLI 问题时,可使用一次。
禁止事项
- 如果没有
cli_config.json或其值为enabled:false,请勿使用 CLI——用户尚未选择启用。仅对绑定的项目(你在其下找到配置文件的目录)进行操作;绝不要open/test/run/build任何其他项目。 - 不要自行安装 Unity CLI;是否安装由用户在面板中决定。
- 绝不要传入
--allow-install(test/run/build支持此参数),也不要使用unity install/install-modules/uninstall/editors upgrade/hub/ 许可证命令,除非用户明确提出要求——安装、升级或移除 Editor 是耗时较长且会更改系统的大型操作,只能由用户执行。 - 不要直接运行
unity mcp——它会启动一个阻塞式 stdio MCP 服务并等待客户端,导致 shell 挂起。 - 不要使用
unity command/unity pipeline/unity run --command——Unity Pipeline 包的途径会重复 UnitySkills REST 已提供的功能,且不属于此工作流。 - 不要使用
unity projects exec或unity projects clean——这些命令会操作多个项目,违反“仅操作绑定项目”的界限。 - 不要使用
unity projects create|new|clone|link|unlink|upgrade、unity templates、unity cloud、unity collab,也不要使用除只读的status/diff/summarize/affected/conflicts/explain/providers之外的任何unity vcs子命令——这些命令会在绑定项目范围之外创建、迁移或改写项目和存储库(本地、远程或 Unity Cloud——在 beta8+ 中,projects create默认启用云端功能)。 - 除非用户明确提出要求,否则不要使用
unity close/projects close(beta8+)——它会在不保存的情况下退出 Editor;优雅关闭需要com.unity.pipeline(否则会出现pipeline_missing→ 将关闭操作交还给用户),而且绝不能由你传入--force(SIGTERM→SIGKILL)。请先通过 REST 保存。 - 不要使用
unity editors prune或unity editors verify——这些命令会修改或验证全局 Editor 安装集合,不属于项目生命周期。 - 不要使用
unity command --detach、unity eval --detach或unity job——分离运行的命令和任务队列属于与绑定项目工作流不同的控制通道。 - 不要使用
unity skill install或unity skill refresh——它们会写入 AI 客户端的配置目录,而且官方 skill 可能绕过 UnitySkills 自身的提示和功能门控;是否安装 skill 由用户在面板中决定。可以使用unity skill show(beta9+)查看——参见 Gate。 - 不要使用
unity shell --protocol ndjson——这是 beta3 的暖进程机器协议,等同于官方 MCP 途径,且不属于此工作流。 - 不要让 CLI 自行更新(
unity self-update,别名为upgrade;self-install/self-uninstall;Homebrew、winget 等),也不要管理其捆绑工具(unity plugin install|remove|upgrade,beta8+)——更新和安装由用户决定。 - 不要解析 CLI 的人类可读输出(其显示语言遵循
unity language设置,例如中文表格标题)——需要以编程方式读取结果时,始终传入--format json --non-interactive。 - 不要将 CLI 可用性视为 REST 工作流的替代方案:
/health有响应后,所有常规操作都应通过 REST 技能完成。
7. Linux 兼容性说明
从 beta4 开始,Linux 上的 Unity CLI 需要 glibc 2.34+,不再支持 Ubuntu 20.04 及更早版本、Debian 11、RHEL/CentOS 8 或 Amazon Linux 2。在这些系统上,CLI 可能会因 glibc 相关错误而无法启动,而不是显示常见的“找不到命令”错误。
不要将此情况视为“未安装 CLI”并提示用户重新安装。应说明兼容性限制:已安装的二进制文件无法在此操作系统/glibc 版本上运行;可选方案包括继续使用 beta3 的功能、升级操作系统或改用其他设备。UnitySkills 不会强制规定全局最低版本;功能支持取决于 CLI 的实际行为:
- beta3 — 旧版
build语义(必须提供--execute-method),没有 NDJSON 终端结果帧。 - beta4+ — 支持 Build Profile、内置桌面构建、NDJSON 终端
type=result帧。 - beta5+ — 提供具名 Editor 信号诊断(
SIGSEGV、SIGILL、SIGTRAP、SIGFPE、SIGBUS)。 - beta6+ —
test退出码8= 失败 /6= 无判定结果;build --timeout;doctor --ci;projects verify;test --shard/--retries/--rerun-failed;来源清单<output>.provenance.json。 - beta8+ —
unity close和vcs/plugin命令组(见 DO NOT);unity upgrade更名为self-update(保留别名);projects create默认创建 Unity Cloud 项目。 - beta9+ —
open在 Editor 提前退出时返回6/OPEN_EDITOR_EXITED(旧版始终返回0);build会拒绝已打开的项目;test --affected;只读的skill show;version --format json;UNITY_NO_CLI_INVOKED_TELEMETRY=1;doctor不再因 macOS 钥匙串提示而卡住;projects verify不再将原生插件文件夹(.bundle/.framework/.androidlib/.plugin)标记为问题。
最稳妥的分支判断方式是在会话开始时运行 <cliPath> --version(beta9+:version --format json)和 <cliPath> <command> --help,并根据二进制文件实际报告的内容采取相应操作。
精确签名
确切名称、参数、默认值和返回值由 GET /skills/schema 或 unity_skills.get_skill_schema() 定义,而非由本文件定义。