十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Unity MCP 的 execute_code 工具:在 Unity 编辑器中动态编译执行任意 C 代码的完整指南

Unity MCP 的 execute_code 工具:在 Unity 编辑器中动态编译执行任意 C 代码的完整指南 Unity MCP 的 execute_code 工具在 Unity 编辑器中动态编译执行任意 C# 代码的完整指南【免费下载链接】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导读execute_code是 Unity MCPAI 助手与 Unity Editor 之间的桥梁在scripting_ext工具组中提供的核心能力它让 LLM 或脚本能够把一段 C# 代码以方法体的形式发送到正在运行的 Unity 编辑器进程中经内存编译后立即执行并返回结果全程不产生任何 .cs 脚本文件、不触发 Domain Reload。读完本文你将掌握该工具的全部参数语义、四种 action 的用法、auto/roslyn/codedom三种编译后端的选型与安装方式、内置安全拦截规则的边界以及 CLI 与 Python 服务端层面的调用链路。一、工具定位与整体架构execute_code属于scripting_ext脚本扩展工具组服务端模块为services.tools.execute_code文档定义在 execute_code 工具参考。它的典型使用场景包括让 AI 直接查询编辑器的运行时状态如Application.unityVersion、Selection.activeGameObject批量修改场景对象、调用 Unity API 完成自动化验证临时试验一段编辑器脚本逻辑而不想在 Assets 目录创建文件。从数据流看一次调用经过三层Python 服务端Server/src/services/tools/execute_code.py声明 MCP 工具签名、校验必填参数、把参数组装成字典后通过send_with_unity_instance路由到当前激活的 Unity 实例多实例场景下由get_unity_instance_from_context决定目标实例Unity 编辑器端MCPForUnity/Editor/Tools/ExecuteCode.cs以[McpForUnityTool(execute_code, Group scripting_ext)]注册HandleCommand根据action分发到不同处理逻辑编译执行把用户代码包装成方法体 → 内存编译Roslyn 或 CodeDom→ 反射调用 → 序列化返回值回传。服务端对响应做了统一归一化始终返回{success, message, data}三元组当 Unity 返回非 dict 或异常时也会兜底转成successfalse的结构参见 Server/tests/test_execute_code.py 中test_non_dict_response_handled等用例。二、参数详解该工具的参数在文档中以表格形式给出下面结合 execute_code.py 的注解与 ExecuteCode.cs 的实际处理逻辑做完整展开参数类型必填说明与默认值actionLiteral[execute, get_history, replay, clear_history]是要执行的操作四种取值分别对应运行代码、列出历史、重放历史、清空历史。其余参数按 action 选择性生效codestr \| Noneexecute 时必填C# 代码必须是合法的方法体可含return。可访问UnityEngine、UnityEditor命名空间。编辑器端长度上限为50000 字符MaxCodeLength为空或缺失时直接返回错误safety_checksbool否是否启用内置的危险模式拦截File.Delete、Process.Start、死循环等。默认true。注意这只是黑名单拦截不是完整沙箱高级绕过是可能的indexint \| Nonereplay 时必填要重放的历史条目下标从 0 开始。超出范围[0, history.Count-1]会返回错误并提示合法区间limitint否get_history返回的历史条数范围被钳制在 1~50。默认 10compilerLiteral[auto, roslyn, codedom]否execute的编译后端。auto优先用 Roslyn安装了 Microsoft.CodeAnalysis 时否则回退 CodeDomroslyn强制 Roslyn支持 C# 12codedom强制传统CSharpCodeProvider仅 C# 6。默认auto几个值得注意的参数行为细节均有源码与测试佐证参数按 action 隔离execute不会携带index/limitget_history不会携带code/index/safety_checksreplay不会携带code/limit/safety_checks见 test_execute_code.py 的参数隔离用例limit 钳制limit999会被压到 50limit-5会被抬到 1服务端与编辑器端都做了这层保护服务端max(1, min(limit, 50))编辑器端Math.Clamp(limit, 1, MaxHistoryEntries)safety_checks 默认开启即使调用方不传编辑器端也会以?? true兜底ExecuteCode.cs。三、四种 action 的用法与返回结构3.1 execute — 执行代码execute是核心 action。用户提供的代码会被包装成一个静态类MCPDynamicCode的静态方法Execute()包装后形如using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using UnityEngine; using UnityEditor; public static class MCPDynamicCode { public static object Execute() { // ← 用户代码从这里开始 } }这意味着不要写class/using声明直接写语句和方法体即可想回传数据就用return。返回值会经过SerializeResult序列化原始类型与 string 直接返回复杂对象尝试转 JSON失败则退化为ToString()。典型请求MCP 调用 / JSON 参数{ action: execute, code: return Application.unityVersion;, safety_checks: true, compiler: auto }成功响应示例编辑器端返回SuccessResponse服务端归一化后{ success: true, message: Code executed successfully., data: { result: 2022.3.20f1, compiler: roslyn } }若编译失败data.errors会携带经过行号偏移修正的诊断信息用户代码行号会被换算而非包装类的真实行号若运行时抛异常data则包含exceptionType、stackTrace与compiler字段。3.2 get_history — 查看执行历史历史记录以内存列表形式保存在编辑器进程内静态字段_history上限50 条超出时淘汰最旧条目。每条记录包含index、codePreview超 500 字符截断加...、success、resultPreview超 200 字符截断、elapsedMs耗时保留 1 位小数、timestampUTC ISO8601、safetyChecksEnabled、compiler。{ action: get_history, limit: 10 }返回形如{success, message: Returning N of M history entries., data: {total, entries: [...]}}历史为空时返回{total: 0, entries: []}。3.3 replay — 重放历史replay会取出历史中指定index的条目用其原始代码 当时的 safety_checks 设置 当时的 compiler 设置重新走一遍execute流程ExecuteCode.cs因此结果可能与当时不同——例如代码依赖的场景状态已经变化。{ action: replay, index: 3 }3.4 clear_history — 清空历史{ action: clear_history }返回Cleared N history entries.直接清空内存列表。四、编译后端auto / roslyn / codedom编译是execute_code的技术核心三档选择对应不同的语言能力与依赖要求实现集中在 ExecuteCode.cs 的CompileAndExecute后端语言支持依赖说明roslynC# 12含LanguageVersion.Latest需要Microsoft.CodeAnalysis系列 DLL通过纯反射调用 Roslyn API编译到内存流后Assembly.Load(byte[])因此即使未安装 Roslyn 也不会编译期报错codedom仅 C# 6随 .NET/Mono 自带的CSharpCodeProvider兼容性兜底路径把引用程序集写入.rsp响应文件以避免命令行超长先编译到临时 DLL 再加载并清理auto取决于探测结果无自动探测先查RoslynCompiler.IsAvailable可用则走 Roslyn否则走 CodeDomRoslynCompilerExecuteCode.cs刻意设计为零编译期依赖通过Type.GetType(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxTree, ...)等字符串定位类型、用反射解析ParseText/CSharpCompilation.Create/Emit并读取EmitResult.Success与Diagnostics一旦探测失败IsAvailable false就回退到 CodeDom。强制roslyn而库不可用时会返回明确提示Roslyn (Microsoft.CodeAnalysis) is not available. Install it via NuGet or use compilercodedom.4.1 如何安装 Roslyn仓库提供了官方安装器 MCPForUnity/Editor/Setup/RoslynInstaller.cs它从 NuGet 下载以下 5 个程序集并解压到Assets/Plugins/Roslyn/NuGet 包版本说明Microsoft.CodeAnalysis.Common4.12.0Microsoft.CodeAnalysis.dllMicrosoft.CodeAnalysis.CSharp4.12.0Microsoft.CodeAnalysis.CSharp.dllSystem.Collections.Immutable8.0.0依赖项System.Reflection.Metadata8.0.0依赖项System.Runtime.CompilerServices.Unsafe6.0.0关键传递依赖Roslyn 的StringTable需要 v6.0.0.0Unity 自带的 v4.x 无法满足安装器还会做版本防御性校验IsInstalled()不仅检查 DLL 是否存在还会比较磁盘程序集版本与声明的 NuGet 版本发现旧版如 v4.x 的 Unsafe 遮蔽 v6会判定为未安装并重新下载。安装完成后AssetDatabase.Refreshexecute_code的auto/roslyn路径即可生效。4.2 内存泄漏防护编译缓存由于每次编译都会生成新的内存程序集而 Mono 无法卸载已加载的程序集重复编译相同代码会造成内存泄漏。编辑器端因此实现了按包装后源码做 key 的编译缓存_compiledCache上限 64 条见 ExecuteCode.cs相同代码重复调用会直接复用上次编译的程序集缓存写满时整表清空。同时OnDomainReload[InitializeOnLoadMethod]会在每次 Domain Reload 时重置所有缓存与已解析的程序集路径。五、安全模型拦截规则与边界safety_checkstrue时代码会先经过CheckBlockedPatterns的大小写不敏感子串匹配ExecuteCode.cs命中即拒绝并返回包含违规模式的错误信息。内置黑名单如下System.IO.File.Delete System.IO.Directory.Delete FileUtil.DeleteFileOrDirectory AssetDatabase.DeleteAsset AssetDatabase.MoveAssetToTrash EditorApplication.Exit Process.Start Process.Kill while(true) while (true) for(;;) for (;;)需要明确两条边界这是黑名单而非沙箱。未列入的破坏性 API如File.WriteAllText、反射调用、AssetDatabase.SaveAssets等仍可执行模式匹配也可被绕过例如拼接字符串构造调用。官方文档与源码注释都反复强调safety_checks blocks known dangerous patterns but is NOT a security sandbox如需放开显式传safety_checksfalse此时File.Delete、Process.Start等均可用后果自负。另外该工具在 MCP 工具注解中被标记为destructiveHintTrue见 execute_code.py即从协议层面提示客户端这是一个具有破坏性潜力的工具调用前应提示用户确认。六、通过 CLI 使用 execute_code除了 MCP 通道仓库还提供了官方 CLI 封装Server/src/cli/commands/code.py适合在终端里快速验证# 执行一段代码方法体形式 unity-mcp code execute return Application.unityVersion; unity-mcp code execute Debug.Log(Camera.main.name); # 从文件读取代码执行 unity-mcp code execute -f my_script.cs # 关闭安全拦截 unity-mcp code execute System.IO.File.WriteAllText(\C:/tmp/a.txt\, \hi\); --no-safety-checks # 查看执行历史默认 10 条可用 --limit 调整 unity-mcp code history unity-mcp code history --limit 5 # 重放历史第 0 条 unity-mcp code replay 0 # 清空历史 unity-mcp code clear-historyCLI 的execute命令会把safety_checks设为not no_safety_checks即默认开启拦截执行成功且data.result非空时终端会打印Result: value。若想绕过 CLI 封装、直接以原始 MCP 参数调用任意工具可使用unity-mcp raw命令见 CLI_USAGE_GUIDE.mdunity-mcp raw execute_code {action: execute, code: return 1 1;} unity-mcp raw execute_code {action: get_history, limit: 5}七、实现细节与源码级原理7.1 服务端参数组装与实例路由execute_code.py 的逻辑非常清晰先解析出unity_instance多实例路由的关键再按 action 组装params_dict过滤掉None值后通过send_with_unity_instance(async_send_command_with_retry, unity_instance, execute_code, params_dict)发送。注意code缺失时服务端直接返回Parameter code is required for execute action.index缺失时返回Parameter index is required for replay action.——参数校验在两端都有。7.2 错误行号映射由于用户代码被包装进MCPDynamicCode.Execute()编译诊断的行号与用户实际行号存在偏移。编辑器端通过WrapperLineOffset 10常量进行换算CodeDom 路径用error.Line - WrapperLineOffsetRoslyn 路径用line 1 - WrapperLineOffset统一取max(1, ...)防止负数让返回的编译错误可以直接对应到用户原始代码行。7.3 CodeDom 路径的两个工程化处理CodeDom 后端有两个值得一提的坑位处理ExecuteCode.cs命令行过长项目有 100 个 asmdef 时CSharpCodeProvider会把每个引用变成/r:...参数超过 Windows 32KB 的CreateProcess上限。解决方案是把所有引用写入.rsp响应文件编译器命令行只传一个短参数netstandard 类型重复定义CSharpCodeProvider无法解析类型转发netstandard.dll与mscorlib/System.Runtime/System.Collections同时加载会报类型定义多次。因此按程序集名过滤掉这些重复项_codedomDuplicateAssemblies必要时按被引用次数 → 版本 → 路径排序去重选择最合适的实现程序集。7.4 测试覆盖仓库为execute_code提供了完整的服务端行为测试Server/tests/test_execute_code.py可作为理解语义的活文档test_execute_forwards_code_to_unity确认code/action被正确转发工具名是execute_codetest_execute_sends_safety_checks_true_by_default默认safety_checksTruetest_get_history_clamps_limit/test_get_history_clamps_negative_limitlimit 钳制到 1~50test_replay_requires_indexreplay 缺index报错test_error_response_normalizedUnity 端错误被归一化成{success:false, message}参数隔离三连测确认不同 action 不会串参数。八、关联资源CustomTools 中的 Roslyn 运行时编译方案若你需要的是在场景里动态编译并挂载 MonoBehaviour/协程的更完整方案仓库在 CustomTools/RoslynRuntimeCompilation/RoslynRuntimeCompiler.cs 提供了配套的独立工具它同样基于 Roslyn 内存编译Assembly.Load(byte[])不写 Assets 目录但支持把编译出的类型作为MonoBehaviour 附加到 GameObject、调用静态入口方法或启动IEnumerator 协程并内置了跨实例共享的编译历史与Window → Roslyn Runtime Compiler编辑器窗口。其安全声明与execute_code一致动态编译的代码拥有与编辑器相同的权限运行不可信代码需自行评估风险。九、小结与最佳实践代码片段只写方法体不需要class/using包裹需要UnityEditor命名空间时直接可用用return回传结果复杂对象会被尝试序列化为 JSON默认开安全拦截保持safety_checkstrue确需执行删除/进程类操作时再显式置false并意识到这不是沙箱优先auto编译器安装好 Roslyn 后自动享受 C# 12 语法旧项目或未装 Roslyn 时自动落到 C# 6 的 CodeDom行为透明善用历史get_historyreplay非常适合让 AI 在多次尝试之间复用上一步的有效代码clear_history用于长会话后清理注意会话边界历史与编译缓存都存在编辑器内存中重启编辑器或 Domain Reload 后即失效——这是设计使然防泄漏不是缺陷。相关深度资料可继续阅读完整的工具参数与组说明见 unity-mcp-skill/references/tools-reference.mdCLI 完整用法见 CLI_USAGE_GUIDE.mdRoslyn 安装与进阶用法见 网站指南 - roslyn。【免费下载链接】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),仅供参考
返回列表