做了一个UnrealEngineMCP的虚幻引擎插件

文章字数:1649

UE5.8 已经带了官方的 MCP 支持,这个插件是参考它的设计思想自己实现的一版,主要用于暂时无法升级引擎的情况。

如果用的是 UE5.8 及以上的版本,直接用官方插件就好,下面这些内容就当是记录一下实现思路。

最近给项目里的 AI 编程助手接了个新能力,让它在编辑器里直接操作 UE 工程。动机挺简单:现在大模型改代码已经很顺手了,可游戏开发里大量活儿不在代码上,而在编辑器里——蓝图、资产、UMG 控件、关卡 Actor 这些可视化资产,AI 光靠改 .cpp / .h 是碰不到的。所以做了个 UnrealEngineMCP 插件,用 MCP(Model Context Protocol)把这些编辑器能力暴露给 AI 助手(opencode、Claude Code 这类)。

架构

一共三层:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
AI 助手 (opencode / Claude Code)
          MCP stdio(始终在线)
        
unreal-mcp wrapper  (Node.js, Tools/mcp-wrapper/)
           编辑器未启动时自动拉起
           发现多个编辑器实例,可指定操作目标
            MCP 调用翻译成极简 HTTP JSON 后端
        
UnrealEngineMCP 插件  (C++,运行在编辑器内)
          GET  /api/health
          GET  /api/tools
          POST /api/tools/call
        
    引擎 Python / 蓝图 / 资产 API

做的时候把「协议」和「工具」拆开了:插件只当工具后端,MCP 协议那一套交给 Node wrapper。原因也简单,UE 5.7 的 HTTPServer 模块不支持 SSE 流式,而 MCP 又依赖流式,与其在插件里硬啃协议,不如把协议解析放到 wrapper(Node + @modelcontextprotocol/sdk),插件端只留几个纯 JSON 的 HTTP 端点,收「工具名 + 参数」回结果。本机走 HTTP 开销是微秒级,工具本身耗时远大于网络,还能直接 curl 调试,Node 那边也零依赖。

run_python 万能入口

插件里最关键的其实是 run_python:在编辑器里跑引擎 Python,import unreal 之后基本什么都能碰。拿它当万能入口,覆盖掉大多数编辑器操作,再补几个便捷读取工具就够了。给 AI 的用法大概这样:

python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import unreal

# 加载并查看蓝图
bp = unreal.load_asset('/Game/UI/WBP_TipsTileView')
print(bp)

# 列出某目录下的资产
print(unreal.EditorAssetLibrary.list_assets('/Game/UI'))

# 查询关卡 Actor
actors = unreal.EditorLevelLibrary.get_all_level_actors()
print([a.get_actor_label() for a in actors])

智能启动与多实例

第一版做完,真用起来发现三个问题:

  1. 忘开编辑器——AI 调工具的时候编辑器没起,直接连不上;
  2. 多实例打架——有时候会开俩编辑器(多半是同一工程开两个),插件写死 8000 端口,第二个绑不上,还可能俩实例读写不同内存状态,改的东西互相踩;
  3. Node 兜底——wrapper 依赖 Node.js,没装的话得给个明白提示,不能静默挂掉。

后来重构了一版(设计文档在 docs/ 里),前两个问题交给 wrapper:

  • 客户端连 unreal-mcp 时如果没编辑器在跑,wrapper 从工程的 EngineAssociation 注册表键解析出引擎路径,自己把编辑器拉起来,轮询等它就绪再处理调用(第一次可能要等 1–3 分钟);
  • 多个编辑器时,wrapper 读 Saved/MCP/instances.json 发现实例,默认选第一个健康的,也能用 list_instances / select_instance 切目标,写操作都走同一个实例;
  • 插件端端口冲突自动顺延(从 8000 往上找空的),实际端口写回注册文件。

工具一览

除了 run_python,还内置了一些便捷工具:

工具说明
list_blueprints列出工程蓝图资产(可按子串过滤)
get_blueprint读取蓝图结构:父类、变量、函数
list_widget_tree读取 UMG WidgetBlueprint 控件树
get_widget_properties读取 UMG 控件实例属性值
create_widget_blueprint创建 UMG WidgetBlueprint
add_widget_to_tree向控件树添加控件
set_widget_properties按类型反射写入控件属性
remove_widget_from_tree从控件树移除控件
exec_command在编辑器机器执行 shell 命令
list_assets列出路径下资产
list_actors列出当前关卡 Actor

还有 wrapper 提供的 list_instances / select_instance 两个实例管理工具。

使用方式

接入不麻烦:把插件目录拷进工程 Plugins/ 并在 .uproject 里启用,npm install 装一下 wrapper 依赖,编译编辑器目标,最后在 .mcp.json 里把 MCP 客户端指到 wrapper 的 index.js 就行。

日常用起来基本无感:直接调工具,编辑器没开它会自己拉起来;开多个实例就先用 list_instances 看眼再 select_instance 锁定。要手动控制的话,编辑器控制台输 UnrealEngineMCP.StartServer 8000 / UnrealEngineMCP.StopServer

开源

插件已经开源在 GitHub:UnrealEngineMCP,有兴趣可以看看。

补充

几个实现上的小点:

  • 新增工具不折腾 wrapper:它靠 GET /api/tools 自动发现工具,JSON Schema → zod 全自动转,新工具只要在 C++ 里实现个 IMCPTool 类并注册,wrapper 一行不用改;
  • 插件是 Editor 模块,Editor-only,不影响打包出来的游戏版本;
  • run_python 能跑任意代码,所以默认只监听本机(bListenOnLocalhostOnly),也只该跑自己信得过的代码——发给 LLM 的数据就是工程内容本身。
本文包含一些 AIGC 辅助生成内容,由作者人工校对整理后发布
本文采用 CC BY-NC-SA 4.0协议,如果对您有帮助或存在意见建议,欢迎在下方评论交流。
本页面浏览次数 加载中...
本页面访客数 加载中...

加载中...