
unity-mcp “T Editing Suite”LLM 驱动的 Unity C# 脚本编辑 CI 增量测试设计【免费下载链接】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本文解读 unity-mcp 仓库中的 CI 提示词.claude/prompts/nl-unity-suite-t.md“Unity T Editing Suite — Additive Test Design”。它定义了一套由 LLM 自主执行的十项增量式脚本编辑测试T-AT-J用于验证 MCP 服务器在真实 Unity 工程中对 C# 脚本的结构化编辑、锚点插入、原子多编辑、SHA 前置校验与幂等行为。读完后你将掌握“提示词即测试”prompt-as-test的 CI 设计模式以及 unity-mcp 脚本编辑链路中script_apply_edits、apply_text_edits、get_sha、validate_script等工具的职责边界与底层实现。一、T 套件在 NL/T 两阶段测试流水线中的定位unity-mcp 用一个 Unity 测试工程TestProjects/UnityMCPTests承载对编辑能力的端到端验收。目标文件是仓库内置的长脚本 LongUnityScriptClaudeTest.cs约 2000 行、无外部依赖的 MonoBehaviour包含HasTarget()、GetCurrentTarget()、Update()、ApplyBlend()等关键方法见 L35-L36。提示词目录.claude/prompts/下有三个姊妹文档构成递进关系nl-unity-suite-nl.mdNL 阶段执行 NL-0NL-4 五个基线用例基线状态捕获、方法替换、锚点注释插入、类尾注释、控制台校验把文件从基线推进到 “State C”nl-unity-suite-t.mdT 阶段本文主角明确“use minimal, precise edits that build on the NL pass state”——即 T 测试不重置文件而是在 NL 阶段留下的 State C 之上继续叠加nl-gameobject-suite.md面向 GameObject 场景的另一条套件。CI 侧还有覆盖门禁脚本 validate-nlt-coverage.sh它逐个检查reports/NL-0_results.xml直到reports/T-J_results.xml共 15 个 XML 片段是否全部非空缺失则退出码为 2。也就是说提示词要求的“每测必产出 XML”与 CI 的脚本校验互为锁扣任何一项用例未执行都会在流水线中显式失败。一个值得注意的细节当前提交中的目标文件已带有// safe animationL105与if (animator null) return; // safety checkL107等标记——从源码结构看这正是 T-C 用例要求在ApplyBlend()中插入的内容说明增量套件确实在该文件上真实运行过且状态被保留。二、CI 运行环境与报告协议2.1 环境与路径约束提示词对环境做了三条硬性约定所有 list/read/edit/validate 调用必须携带project_root: TestProjects/UnityMCPTests与ctx: {}URI 只使用规范形式主形式为mcpforunity://path/Assets/...绝不能把project_root嵌进 URI在受支持时也可用相对形式Assets/...CI 预置$JUNIT_OUTreports/junit-nl-suite.xml预先创建禁止读写与$MD_OUTreports/junit-nl-suite.md由 JUnit 合成。这与服务器端的路径归一化逻辑相互印证script_apply_edits在 Server/src/services/tools/script_apply_edits.py 的_normalize_script_locator()L585-L639中会剥离mcpforunity://path/、file://前缀并折叠Assets/.../X.cs/X.cs这类重复尾巴保证两种 URI 形式最终定位到同一文件——这正是 T-G 用例路径归一化要验证的行为。2.2 严格 XML 片段报告每个测试结束后必须“立即”向reports/TESTID_results.xml写入恰好一个testcase根元素且文件内不允许出现前言/后记、代码围栏或任何 XML 之外的字符testcase nameT-D — End-of-Class Helper classnameUnityMCP.NL-T system-out![CDATA[ (evidence of what was accomplished) ]]/system-out /testcase要求还包括TESTID 必须是 T-AT-J 之一name属性必须以精确的测试 ID 开头失败时仍要写入片段并附failure messagereason/。文档后半部分为 T-FT-J 各自给出了可直接套用的 XML 模板如 T-I 的模板要求记录 “Overlapping edit: failed cleanly (error captured). / Stale hash edit: failed cleanly (error captured). / File unchanged.”保证证据格式统一、可被后续 JUnit 聚合。2.3 转录最小化规则Transcript Minimization由于执行者是 LLM提示词专门约束了它的“话痨”倾向控制 CI 转录体积与 Token 成本不复述工具返回的 JSON总结不超过 2 行短句绝不粘贴完整文件内容展示匹配时只给匹配行及前后 ±1 行优先用find_in_file定位避免read_resource确需读取时限制head_bytes ≤ 256或tail_lines ≤ 10每个system-out≤ 400 字符且不含 SHA控制台证据取最后 10 行log/info至多 3 条errorinclude_stacktrace:false片段内合计 ≤ 3 行无错误就写 “no errors”避免引用多行 diff改用标记marker指代。三、工具映射与操作护栏Tool GuardrailsT 套件的工具白名单为AllowedTools: Write, mcp__UnityMCP__manage_editor, mcp__UnityMCP__list_resources, mcp__UnityMCP__read_resource, mcp__UnityMCP__apply_text_edits, mcp__UnityMCP__script_apply_edits, mcp__UnityMCP__validate_script, mcp__UnityMCP__find_in_file, mcp__UnityMCP__read_console, mcp__UnityMCP__get_sha并按职责划清边界工具职责关键约束script_apply_edits锚点/正则/结构化编辑仅允许anchor_insert、replace_method、insert_method、delete_method、regex_replaceanchor_insert必须显式指定position: before或after禁用anchor_replaceapply_text_edits精确行列范围 / 原子批量文本编辑多个 range 之间不得重叠多点文本微调需先用find_in_file计算范围get_sha哈希探测只返回{sha256, lengthBytes, lastModifiedUtc}不返回文件体validate_script结构校验每次编辑后以level:standard执行find_in_file动态定位用于找方法/标记的当前位置替代硬编码行号“禁用anchor_replace”这条护栏值得深挖。查看服务器端 script_apply_edits.py 的工具描述可以看到anchor_replace在生产路径中是可用的操作之一L683op: replace_method | insert_method | delete_method | anchor_insert | anchor_delete | anchor_replace但在 CI 套件中被刻意排除——因为在锚点模糊时“替换”是破坏性最强的操作测试中只保留插入/删除/整方法替换这类边界明确的操作可以把失败面收敛到可控范围。服务器端还有大量防御字段别名归一化class_name→className等L772-L812、anchor_insert缺少anchor时返回带rewrite_suggestion的missing_field错误L929-L941使 LLM 能从机器可解析的提示中自我纠正——这与 T-I 用例“验证错误响应是有信息量的”目标直接对应。四、增量测试设计原则Additive Design提示词相对传统“reset-based”每测后恢复基线方案列出了五条核心原则动态定位Dynamic Targeting用find_in_file找方法/内容绝不硬编码行号状态感知State Awareness每个测试预期文件处于上一个测试留下的状态基于内容操作Content-Based Operations按方法签名定位方法、按名称定位类而非坐标累积校验Cumulative Validation整条序列执行过程中文件必须始终保持结构完整可组合性Composability测试要展示各操作在真实工作流中如何协同。状态跟踪方面每个测试后用get_sha记录文件哈希并在 T-F/T-G/T-I 中把它作为apply_text_edits的前置条件专门验证stale_file语义同时用内容签名方法名、注释标记核对预期状态SHA 值本身不得出现在报告片段中。错误恢复策略是“失败不恢复”NO RESTORATION某测试失败时记录当前状态但继续执行下一个测试适配实际当前状态而非预期状态——既简化了基础设施无需恢复脚本与快照也让故障不会级联同时验证了编辑操作在各种文件条件下的韧性。这些设计在实现层有实打实的支撑前置哈希校验Unity 侧ManageScript的ApplyTextEdits要求precondition_sha256缺失返回precondition_required不匹配则返回stale_file并附带expected_sha256与current_sha256供重试见 MCPForUnity/Editor/Tools/ManageScript.cs。T-G 用例正是利用这一机制同一编辑先用mcpforunity://path/...URI 成功再相对路径 旧 SHA 重试预期第二次收到stale_file后用新 SHA 成功。无操作短路服务器端在本地应用编辑后若内容未变化会直接短路返回{no_op: true, evidence: {reason: identical_content}}script_apply_edits.py。T-J 用例重复同一anchor_insert/regex_replace并预期no_op: true验证的正是这条幂等路径。类尾大括号的“智能锚点”T-D 要求在 NL-3 的尾部注释之后、类闭合大括号前插入方法提示词称之为 “smart anchor matching”。实现上服务器对形如}\s*$的闭合括号模式会调用_find_best_closing_brace_match()L524-L568先用单遍 C# 词法器_iter_csharp_tokens能正确跳过普通/逐字/插值/原始字符串与注释计算每个候选}的大括号嵌套深度优先选择最浅层最外层且位置最靠后的大括号——即类结束位置而不是误插到某个方法体里。这正是 T-D “在类尾插入永久辅助方法而不破坏结构”能稳定成立的底层原因。五、T-AT-J 用例规格十个测试按序执行状态逐级叠加State C → I用例目标关键操作预期终态T-A临时辅助方法生命周期插入→验证→删除的完整循环定位GetCurrentTarget()位置可能因 NL-2 注释而漂移插入private int __TempHelper(int a, int b) a b;确认可编译用结构化删除移除回到 State C辅助方法被移除其余改动完整T-B方法体内部编辑不改结构地修改方法内部find_in_file定位已被 NL-1 改过的HasTarget()把 return 语句改为return true; /* test modification */validate_script(standard)确认文件仍平衡State C 修改后的HasTarget()T-C另一方法内部编辑证明不同方法的编辑互不干扰内容搜索定位ApplyBlend()内部加空检查if (animator null) return; // safety check保留签名与结构State D 修改后的ApplyBlend()T-D类尾辅助方法在类尾添加永久辅助方法用智能锚点匹配找到当前类结束大括号NL-3 尾部注释之后在大括号前插入private void TestHelper() { /* placeholder */ }validate_script立即写reports/T-D_results.xmlState E 类尾前的TestHelper()T-E方法演化生命周期字段 伴生方法的 插入→修改→定型插入private int Counter 0;find replace 为private int Counter 42; // initialized添加private void IncrementCounter() { Counter; }State F Counter字段 IncrementCounter()T-F原子多编辑单次原子操作完成多处协同编辑先读当前文件计算精确 range一次原子调用同时HasTarget()加// validated access、ApplyBlend()加// safe animation、类尾加// end of test modifications三处编辑均基于同一文件快照随后validate_script并写reports/T-F_results.xmlState G 三处协同注释T-G路径归一化验证两种 URI 形式等价同一编辑分别用mcpforunity://path/Assets/Scripts/LongUnityScriptClaudeTest.cs与Assets/Scripts/LongUnityScriptClaudeTest.cs执行第二次预期返回stale_file用更新后的 SHA 重试成功输出reports/T-G_results.xml记录 stale 处理证据State H无内容变化T-H重度修改后文件上的校验验证校验器在大量修改后的表现对当前状态运行validate_script(level:standard)确认无结构性错误写reports/T-H_results.xmlState H仅校验T-I失败面测试真实修改文件上的错误处理尝试重叠编辑应干净失败尝试使用过期 SHA 的编辑应干净失败确认错误响应有信息量文件必须保持不变写含错误证据的reports/T-I_results.xml仍只含一个testcaseState H失败操作不修改文件T-J幂等性 终检重复操作的确定性行为结构化插入{op:anchor_insert,anchor:// Tail test C,position:after,text:\n // idempotency test marker}重复同操作 → 预期no_op: trueregex_replace删除(?m)^\s*// idempotency test marker\r?\n?再删一次 → 预期no_op: truevalidate_script最后做一次仅错误扫描至多 3 条无则写 “no errors”立即写reports/T-J_results.xmlState H 幂等行为得到验证补充两条横向规则Late-Test Editing Rule修改方法体时必须走script_apply_edits若方法是表达式体如本文件的GetCurrentTarget() currentTarget先转换为块体或整体替换方法定义编辑后运行validate_script出错即回滚插入代码统一用//注释。每个用例完成后的固定动作序列find_in_file验证关键标记存在 →validate_script(level:standard)检查结构完整 → 更新 SHA 跟踪供下一用例作前置条件 → 立即写 XML 片段失败也要写→ 在证据中简要记录累积变更遵守转录最小化规则绝不粘贴原始工具 JSON。T-J 末尾把“最终控制台扫描”折叠进来使 T 阶段以一个单一证据点收尾避免多开一个纯校验用例。六、动态定位模式与源码对照提示词给出了一组“坐标 → 内容感知”的改写对照值得完整保留不推荐——硬编码坐标{startLine: 31, startCol: 26, endLine: 31, endCol: 58}推荐——内容感知定位# 先找当前方法位置 find_in_file(pattern: public bool HasTarget\\(\\)) # 再根据命中位置计算编辑范围按签名定位方法{op: replace_method, className: LongUnityScriptClaudeTest, methodName: HasTarget}基于锚点的插入{op: anchor_insert, anchor: private void Update\\(\\), position: before, text: // comment}这套“先定位、再算 range、后提交”的模式对应服务器端的两条路由路径。script_apply_edits收到编辑列表后script_apply_edits.py全部为结构化操作STRUCT集合时直接转发 Unity 的结构化编辑器且默认refresh: immediate并在编辑前记录pre_sha用于断线后的 SHA 复核包含文本操作时先经 Unityread取出文件全文在服务器侧把anchor_insert/regex_replace等换算成行列范围at_edits计算原文sha256作为precondition_sha256再以applyMode: atomic多 span 时自动升级为原子模式下发manage_script/apply_text_edits混合批次STRUCT TEXT走 “text-first” 路由先原子提交文本编辑再提交结构化编辑。T-F 的“单次原子多编辑”因此不是提示词的愿望而是链路能力三处 range 由同一快照计算、互不重叠一次性下发任一 span 越界如start out of range (line x, col y)见 ManageScript.cs或前置哈希不匹配stale_file都会使整批回滚这正是 T-I 要观察的“干净失败”。校验侧同样分层validate_script(level:standard)在 ManageScript.cs 中按级别执行 Roslyn 语法校验可用时、Unity 特定规则、通用语义规则等多层检查若编辑造成括号不平衡响应会附带形如unbalanced_braces at line N. Call resources/read for lines X-Y and resend a smaller apply_text_edits that restores balance.的可操作提示L721 附近使 LLM 能按提示缩小重试范围——这是“增量序列中文件必须始终结构完整”这条原则的执行保障。七、增量设计的收益与适用边界提示词总结的六点收益可视为对这套 CI 设计的验收标准贴近真实工作流测试模拟真实开发中“在持续变化的文件上编辑”的模式而非只在干净基线上编辑鲁棒性证明编辑操作在演化中的文件上依然有效可组合性验证证明各操作能良好协同基础设施简化不需要恢复脚本或快照更好的故障分析失败不级联每个测试适配当前现实状态演化测试验证 SDK 正确处理累积文件修改。同时该提示词的适用边界也应清晰它假定运行在 unity-mcp 的 CI 中reports/目录预置、Unity Editor 可用 MCP 服务器、目标文件固定并“BAN”了白名单之外的工具与目录创建它不是面向人类用户的教程而是给 CI 中 LLM Agent 的自主执行剧本。若要复用该模式可参照 nl-unity-suite-nl.md 与 nl-unity-suite-t.md 的“分阶段 状态命名 每测产出 JUnit 片段 脚本门禁”的组合替换为你自己的目标文件与用例序列并用类似 validate-nlt-coverage.sh 的覆盖检查保证每个用例都有可审计的证据落盘。八、延伸阅读仓库内路径提示词本体.claude/prompts/nl-unity-suite-t.md、NL 阶段.claude/prompts/nl-unity-suite-nl.md被测目标脚本TestProjects/UnityMCPTests/Assets/Scripts/LongUnityScriptClaudeTest.cs服务器端编辑工具实现Server/src/services/tools/script_apply_edits.py、定位工具Server/src/services/tools/find_in_file.pyUnity 侧apply_text_edits/get_sha/校验实现MCPForUnity/Editor/Tools/ManageScript.csCI 覆盖门禁scripts/validate-nlt-coverage.sh【免费下载链接】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),仅供参考