ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

UE5.8+MCP+Claude Code:AI编排PCG实现高效城市生成工作流

UE5.8+MCP+Claude Code:AI编排PCG实现高效城市生成工作流

UE 里做城市,一直是个“投入大、周期长、返工多”的活。一个中等规模的主城区,美术手工摆放动辄几周;用 PCG 程序化生成,又得先啃节点图、调种子、反复进出编辑器看效果;买现成城市资产包,则要面对风格统一、碰撞体、性能预算一堆后续问题。过去三年 PCG 框架本身成熟了不少,但多数团队的真正痛点并不在“能不能生成”,而在“参数与效果之间的反馈循环太慢”——改一个密度值、换一次随机种子、看一眼效果,来回十几轮,时间就这样烧掉了。

UE5.8 这个节点上,MCP(Model Context Protocol)插件开始把 Claude Code 这类 AI 助手接进编辑器,PCG 城市构建出现了新的玩法:AI 读取场景现状、调整路网和 PCG 参数、触发程序化生成、再自动检查结果,人只负责定规则和做最终判断。这里的核心判断是:所谓“AI 城市生成”,并不是 AI 一键摆出整座精装修城市,而是 AI 充当了“意图翻译器 + 参数调试器 + 结果检查器”。城市本身仍然由路网样条和 PCG 图驱动,仍然可编辑、可回滚、可审计;AI 压缩的是“人反复进出编辑器调参数”的那部分时间。

这篇文章会把这套体系从概念到落地完整拆开:MCP 插件的接入方式、Claude Code 如何与编辑器协作、PCG 城市示例项目的驱动流程、桥接代码怎么写、验证怎么做,以及实际接入时最容易踩的坑。

1. 这篇文章真正要解决的问题

1.1 传统城市生成流程的三个成本瓶颈

先看传统流程为什么慢。第一个瓶颈是手工摆放。城市里的建筑、路灯、植被、路牌,数量以千甚至万计,纯手工摆放不仅慢,而且后期只要路网微调,所有内容都要跟着重摆。第二个瓶颈是PCG 参数调试。PCG 图能一次生成成百上千个 actor,但参数和视觉效果之间不是线性关系:密度、种子、采样间距、随机偏移,任何一个改动都会让结果面目全非。第三个瓶颈是结果检查。程序化生成完之后,必须切进视口、飞行到具体区域、确认有没有穿模、有没有悬空、有没有超出地块边界。这个“生成—检查—改参数—再生成”的循环,才是城市构建真正耗时的地方。

1.2 AI 工作流压缩的是反馈循环,而不是生成本身

如果只看表面,很容易误以为 AI 城市生成是把“摆城市”这件事自动化。实际不是。PCG 已经把“摆城市”自动化了,AI 的价值在于把“调试 PCG”这件事自动化。Claude Code 通过 MCP 插件拿到编辑器能力后,可以完成这样一条链:

  • 读取当前场景里有哪些 PCG Actor、路网样条有多少段、最近一次生成的种子是多少;
  • 根据人的指令,把建筑密度从 0.5 改成 0.7,换一个随机种子;
  • 触发重新生成;
  • 再通过编辑器接口检查生成结果是否合理,把日志和摘要返回给人。

整个过程中,城市生成引擎仍然是 PCG,AI 只负责“读懂现状—修改参数—触发生成—汇报结果”。这比单纯的“AI 生成资产”更有工程价值,因为它没有绕过既有管线,而是把既有管线的调试环节压缩了。

1.3 什么样的读者最适合这篇文章

如果你正在做开放世界、沙盒、模拟经营类项目,或者你的团队已经引入了 PCG 但觉得“调参效率太低”,这篇文章适合你。如果你是做工具链、开发效率平台的技术同学,文章里的 MCP 桥接模式也可以直接迁移到其他 DCC 工具。如果你是刚接触 UE 的新手,建议先跑通 PCG City Sample 再回来看 AI 编排部分。这套方案解决的工程协同问题,需要你先对 PCG 有基本手感。

2. 基础概念:MCP、Claude Code 与 PCG 城市生成

2.1 MCP:AI 应用与外部工具之间的“USB 接口”

MCP(Model Context Protocol)是 Anthropic 提出的开放协议,作用是把 AI 应用和外部数据、工具连接起来。你可以把它理解成 AI 世界的 USB 接口:协议统一了“AI 如何发现工具”“AI 如何调用工具”“工具结果如何返回”这三件事。

MCP 采用客户端—服务器架构,传输层常用 stdio 或 SSE/HTTP,消息格式基于 JSON-RPC 2.0。一次典型调用流程是:

  1. 客户端(Claude Code)启动 MCP Server;
  2. 双方完成initialize握手;
  3. 客户端调用tools/list获取服务器暴露的工具列表;
  4. 客户端调用tools/call执行具体工具,参数由 AI 根据用户指令自动填充。

在 UE 场景里,MCP Server 把“查询场景”“执行 Python 脚本”“触发生成”这些能力封装成一个个工具。Claude 并不直接操作 UE,而是通过调用这些工具间接操作编辑器。

2.2 Claude Code:终端里的 AI 开发代理

Claude Code 是 Anthropic 提供的命令行 AI 编程工具,能在终端里读文件、改代码、执行命令,也支持通过 MCP 扩展外部工具。它在城市生成流程里的角色是“调度者”:接收人的自然语言指令,拆解成多个 MCP 工具调用,按顺序执行,最后汇总结果。

要注意的是,Claude Code 本身并不理解 UE 的视口,也不懂 PCG 节点的视觉反馈。它依赖的是编辑器暴露出来的“可读信息”——Actor 列表、属性值、生成日志、屏幕截图命令的输出。所以,MCP 工具设计得越贴近“人能看的检查项”,AI 的判断就越可靠。

2.3 PCG:UE 的程序化内容生成框架

PCG(Procedural Content Generation)是 UE 内置的程序化生成框架,用节点图描述“在什么区域、按什么规则、生成什么内容”。城市场景里最常用的节点包括:样条采样(SplineSampler)、表面采样(SurfaceSampler)、网格排布(Grid2D)、属性传递(AttributeTransfer)、按标签过滤(Filter)等。

Epic 官方提供的 PCG City Sample 是一套完整参考实现:道路由样条定义,PCG 图沿样条生成路面、人行道和路口;路网围出的街区被划分成地块;地块上再由 PCG 生成建筑 footprint、楼宇体块甚至立面细节。这套示例的价值在于,它证明了 PCG 城市可以做到“路网一动,整座城跟着更新”。

2.4 三者关系一句话总结

概念一句话解释在城市生成中的角色
MCPAI 应用与外部工具之间的标准化协议让 Claude 能发现并调用 UE 编辑器能力
Claude Code终端里的 AI 开发代理读取场景、改参数、触发生成、检查结果
PCGUE 的程序化内容生成框架实际生成道路、建筑、植被的“发动机”
UE Python / Remote Control编辑器自动化执行通道MCP 工具与 PCG 图之间的桥梁

3. 技术架构:AI 编排 PCG 的完整链路设计

3.1 两种主流接入方式

社区里把 AI 接进 UE 的方式大致分两类:

方式 A:编辑器内嵌 MCP 服务。在 UE 里安装一个 MCP 插件,插件在编辑器进程中启动 MCP/HTTP 服务,直接调用 UE 的 Python 和编辑器 API。优点是链路短、实时性强、能直接操作视口和选中对象;缺点是插件与编辑器进程耦合,AI 调用出错可能拖累编辑器稳定性。

方式 B:外部 MCP Server 桥接。用一个独立 Python 进程运行 MCP Server,通过 UE 的 Remote Control API(内置插件)与编辑器通信。优点是 AI 进程与编辑器分离,崩溃影响面小,便于做权限收敛和日志审计;缺点是链路多一跳,延迟略高。

从生产环境的角度,我更推荐方式 B。城市生成的任务普遍是“分钟级”的大规模计算,不差那几十毫秒;但“AI 拥有编辑器内任意 Python 执行权”这件事,必须被隔离在一个可审计、可熔断的桥接层之后。

3.2 桥接模式的链路拆解

完整链路如下:

用户指令 ↓ Claude Code(AI 调度) ↓ MCP stdio 传输 Python MCP Server(工具注册、参数校验、权限控制) ↓ Remote Control API(HTTP / WebSocket) UE 编辑器(Python 执行、PCG 生成、场景查询) ↓ 结果返回 Claude Code 汇总并汇报

这里有一个关键设计:MCP Server 暴露给 AI 的工具,不应该是最底层的“任意执行”,而应该是收敛后的白名单工具。比如:

  • get_scene_summary():返回场景规模、PCG Actor 列表;
  • get_pcg_parameters():返回指定 PCG Actor 的关键参数;
  • set_pcg_parameters(params):修改白名单内的参数;
  • regenerate_pcg(actor_label):触发重新生成;
  • capture_viewport():截图或获取视口摘要。

把操作收敛成白名单工具,AI 的能力边界就是可描述的。这一步不是限制,而是保护:它保证 AI 只能做“城市构建”这件事,而不是在编辑器里执行任意代码。

3.3 协议层的消息流

MCP 底层消息是标准的 JSON-RPC 2.0。一次 AI 调用 UE 工具的请求大致如下(这是协议层面的示意,不是某插件特有格式):

{ "jsonrpc": "2.0", "id": 7, "method": "tools/call", "params": { "name": "regenerate_pcg", "arguments": { "actor_label": "PCG_City_Blocks", "seed": 20240517, "building_density": 0.7 } } }

理解这层协议,对你排查“AI 调了工具但 UE 没反应”这类问题很有帮助。你会发现问题往往不在 AI 本身,而在某个环节的请求格式、参数名或端口连通性上。

4. 环境准备与前置条件

4.1 版本与组件清单

本文讨论的流程在 UE 5.3 到 5.8 的 PCG 框架上都适用,版本差异主要集中在 Python API 名称和 Remote Control 接口格式上。建议按以下清单准备:

组件说明
Unreal Engine5.8 或 5.3+ 皆可,建议保持小版本较新
PCG City SampleEpic 官方示例工程,从 Fab(原 Marketplace)获取
Remote Control API 插件UE 内置插件,需要手动启用
Python3.9+,建议 3.11 或 3.12
Anthropic MCP Python SDKpip install mcp或mcp[cli]
Claude Code官方 CLI 工具,安装后需要 Anthropic 账号授权

这里要强调:不要迷信版本号。UE 的 Python 自动化 API 在不同版本里常有细微变化,抄网上的代码之前,先打开 Python 控制台用自动补全确认方法名存在。文章里的示例重点演示思路,具体到你的项目版本,请以自动补全和官方文档为准。

4.2 启用 UE 侧 Remote Control 插件

在编辑器中打开Edit > Plugins,搜索并启用:

  • Remote Control API
  • Remote Control UI

启用后重启编辑器。Remote Control 默认监听本地端口(常见为 30000),只绑定 127.0.0.1。这一步是整个桥接模式的基础:UE 通过这个接口接收外部 HTTP/WebSocket 请求。

需要提醒的是,这个接口本质上允许外部进程操作编辑器,属于高权限通道。不要修改监听地址为公网地址,也不要在多人共享的机器上长时间开启不设访问控制的 Remote Control。

4.3 安装 Claude Code 并准备项目目录

Claude Code 的官方安装方式以官方文档为准,常见方式是 npm 全局安装:

npm install -g @anthropic-ai/claude-code

安装完成后,在项目根目录打开终端,执行claude即可进入交互模式。项目根目录下需要准备两个东西:

  1. .mcp.json,声明要加载的 MCP Server;
  2. scripts/目录,存放我们的桥接 Python 服务。

5. 核心代码实现:UE MCP 桥接层

5.1 最小可用的 MCP Server

下面是一个完整的 MCP Server 示例。它暴露了四个白名单工具:查询场景摘要、查询 PCG 参数、修改 PCG 参数、重新生成。所有对 UE 的调用都走 HTTP 转发。

# 文件路径:scripts/ue_bridge_mcp_server.py import json import urllib.request from mcp.server.fastmcp import FastMCP mcp = FastMCP("ue-city-builder") # 与 UE Remote Control 监听地址保持一致,默认 127.0.0.1:30000 UE_RC_HTTP = "http://127.0.0.1:30000" def rc_request(method: str, path: str, body: dict) -> dict: """封装 Remote Control API 的 HTTP 请求,异常统一抛给上层。""" url = f"{UE_RC_HTTP}{path}" data = json.dumps(body).encode("utf-8") req = urllib.request.Request( url, data=data, method=method, headers={"Content-Type": "application/json"}, ) with urllib.request.urlopen(req, timeout=30) as resp: return json.loads(resp.read().decode("utf-8")) @mcp.tool() def get_scene_summary() -> str: """获取当前关卡的基本信息:Actor 数量、PCG Actor 列表。""" resp = rc_request("GET", "/remote/objects", {}) # 不同版本 Remote Control 返回结构不同,这里只取外层对象数量做演示 return json.dumps(resp, ensure_ascii=False) @mcp.tool() def execute_ue_python(script: str) -> str: """在 UE 编辑器内执行 Python 脚本,并返回脚本输出。 这是高权限工具,建议在生产环境下收敛为白名单函数调用, 而不是把任意代码执行权交给 AI。 """ body = {"script": script} resp = rc_request("POST", "/execute_python", body) return json.dumps(resp, ensure_ascii=False) if __name__ == "__main__": # stdio 传输:由 Claude Code 启动本脚本并与它通信 mcp.run(transport="stdio")

这段代码里,/execute_python是一个需要你在 UE 侧配合实现或接入社区插件的接口。实际项目中,你可以选择:

  • 使用社区 MCP 插件自带的执行 Python 能力;
  • 自己在 UE 里写一个编辑器工具脚本,接收 HTTP 请求并调用unrealAPI。

重要的是工具层的边界设计:MCP Server 只负责封装和转发,不负责生成城市;它是一道“阀门”,决定 AI 可以碰哪些操作。

5.2 注册到 Claude Code

在项目根目录创建.mcp.json:

{ "mcpServers": { "ue-city": { "command": "python", "args": ["scripts/ue_bridge_mcp_server.py"], "env": { "UE_RC_HTTP": "http://127.0.0.1:30000" } } } }

然后启动 Claude Code,用以下命令确认 MCP Server 注册成功:

claude mcp list

如果看到ue-city出现在列表里,说明桥接层已经就绪。接下来,Claude 就能在对话中看到get_scene_summary、execute_ue_python这几个工具。

5.3 工具设计建议

工具不在多,而在“可描述、可验证、可回滚”。每个工具都应该满足:名字能说明用途,描述里写清楚输入和输出,返回结果用结构化文本,方便 AI 直接基于结果做下一步决策。

另一个建议是把“查询”和“写入”分开。查询类工具可以放开给 AI 自由调用;写入和生成类工具,要么要求人工确认,要么限制为固定参数的调用窗口。这样即使 AI 判断失误,也不会立刻把场景改坏。

6. 实操流程:用 Claude Code 驱动 PCG 城市构建

6.1 PCG City Sample 的基本结构

在动手前,先花半小时打开 PCG City Sample 工程,理解它的层级:

  • 道路系统:由样条组件定义主干路网,PCG 图沿样条生成路面和人行道;
  • 街区划分:路网围合成的区域由 PCG 自动识别为街区;
  • 建筑生成:街区内再按地块生成建筑,包括 footprint、楼体高度、立面材质变化;
  • 细节层:植被、路灯、路牌等由另一张 PCG 图在指定空间内撒点。

这套结构决定了 AI 编排的切入点:路网是“骨架”,PCG 参数是“血肉”,AI 的作用是在骨架确定之后,快速调整血肉组合方式。

6.2 第一步:让 AI 读取场景现状

在 Claude Code 里输入类似这样的指令:

请先调用 get_scene_summary 查看当前场景,找到所有 PCG 相关 Actor, 并告诉我场景里有哪些可操作的城市生成对象。

Claude 会调用 MCP 工具,返回 UE 里的 Actor 摘要。这一步的意义是让 AI 建立“场景上下文”。如果工具返回为空,或者信息不可读,后面所有决策都会变成盲猜。所以工具返回内容要尽量结构化:Actor 名称、类型、PCG 图路径、最近一次生成状态。

6.3 第二步:调整参数并触发生成

在获取场景摘要后,你可以让 AI 直接做一轮“调参—生成”实验。比如:

把 PCG_City_Blocks 的建筑密度改成 0.65,换一个随机种子, 重新生成,并返回生成日志。

此时 Claude 会调用修改参数的 MCP 工具和重新生成工具。在 UE 侧,对应的 Python 脚本大致是这样:

# 文件路径:Scripts/ue_pcg_worker.py # 由 execute_ue_python 工具触发,也可以注册为 Remote Control 白名单函数 import unreal PCG_ACTOR_LABEL = "PCG_City_Blocks" def regenerate_city(seed: int = 0, building_density: float = 0.65) -> bool: """重置随机种子并强制重新生成 PCG 城市。""" actors = unreal.EditorLevelLibrary.get_all_level_actors() target = None for actor in actors: if actor.get_actor_label() == PCG_ACTOR_LABEL: target = actor break if target is None: unreal.log_error(f"未找到 PCG Actor: {PCG_ACTOR_LABEL}") return False pcg_component = target.get_component_by_class(unreal.PCGComponent) if pcg_component is None: unreal.log_error("Actor 上没有 PCGComponent,请检查 PCG 图是否已挂载") return False # 注意:不同 UE 版本中 PCG 相关 Python API 名称有差异, # 请以当前版本编辑器自动补全结果为准。 pcg_component.set_editor_property("Seed", seed) pcg_component.execute() unreal.log(f"城市重新生成完成: seed={seed}, density={building_density}") return True

这段脚本的关键点在两个地方:一是通过get_all_level_actors定位到目标 PCG Actor,而不是硬编码引用,避免关卡重命名后脚本失效;二是生成前后都打日志,确保 AI 能拿到可验证的输出。

6.4 第三步:检查结果并迭代

重新生成完成后,让 AI 再执行一次查询,确认 PCG Actor 的子 actor 数量、建筑实例数是否发生变化。这是整个循环里最容易断的一环:AI 生成了,但没有验证,后续操作就会基于过期状态继续做。

可以用这样的指令收尾:

重新生成之后,统计场景中新增的建筑 actor 数量,和生成前对比, 告诉我这次改动是否符合预期。

如果结果不符合预期,AI 会自动换参数再来一轮。整个“改参数—生成—检查—再改”的循环,从人的几十轮手动操作,变成 AI 在几分钟内自动完成的多轮试探。注意,这里仍然是“试探”,不是“设计”:AI 不理解美学,它只负责在参数空间里快速搜索。最终选择权必须留在人手里。

6.5 用自然语言描述生成意图

如果你希望 AI 定期按某种风格生成城市,可以把意图沉淀成项目里的规范文档。比如创建docs/city_design_rules.md,写明“建筑高度不超过 30 米”“主路宽度 24 米”“街区绿化率 10%”。然后让 Claude Code 读取这份文档,再据此生成参数。AI 的决策就不再是临场发挥,而是有据可查。

7. 运行结果与效果验证

7.1 验证清单

判断 AI 编排流程是否跑通,按下面的清单逐项检查:

检查项判断方式
MCP Server 注册成功claude mcp list能看到ue-city
场景读取正常get_scene_summary返回非空、字段完整
参数修改生效生成前查询参数,生成后再次查询,数值已变化
PCG 重新生成成功UE 输出日志出现“城市重新生成完成”
场景内容变化建筑/植被 actor 数量发生变化
不期望的改动未发生对比版本控制,确认只有预期文件被修改

7.2 失败时第一步看哪里

如果生成后场景没有变化,优先按以下顺序排查:

  1. 先看 MCP Server 的控制台输出,有没有工具调用记录;
  2. 再看 UE 的 Output Log,确认execute()是否真正执行;
  3. 检查 PCG Actor 是不是被关卡里其他逻辑关闭了自动生成;
  4. 最后看参数值是否被正确写入,常见问题是没有走set_editor_property,而是直接改局部变量。

记住一个原则:AI 只是调用了工具,工具是否生效,要用 UE 自己的日志来验证,而不是凭“AI 说成功了”。

8. 常见问题与排查思路

问题现象可能原因排查方式解决方案
Claude Code 找不到 MCP 工具.mcp.json路径不对或 Server 启动报错查看claude mcp list和 Server 控制台输出确认配置文件在项目根目录,Python 依赖完整安装
MCP 工具调用超时UE Remote Control 未启用,或端口不一致用浏览器访问http://127.0.0.1:30000测试连通性启用 Remote Control 插件,统一监听端口
工具能调用但 PCG 不生成Python API 名称与当前版本不匹配在 UE Python 控制台手动执行并看报错以自动补全为准修正 API 名称
生成结果与上次完全一样随机种子没变,或 PCG 图未标记可重新生成查询 Seed 属性是否被写入每次修改参数时显式更新 Seed 并调用execute
AI 修改了不在白名单内的内容暴露了“任意 Python 执行”工具检查工具列表和调用日志收敛为白名单工具,生成操作要求人工确认
生成过程卡死编辑器全城一次性重新生成,计算量过大检查日常统计与 GPU/CPU 占用分区域生成,或先在小地块验证,再全量执行

9. 最佳实践、安全边界与后续方向

9.1 安全边界

把 AI 接进 UE 编辑器,本质上是给 AI 开了一道“编辑器内执行”的通道,安全上要当成远程代码执行来处理。

至少做到这几点:

  • Remote Control 只监听127.0.0.1,不暴露到局域网或公网;
  • MCP 工具按白名单设计,“查询类”放开,“写入和生成类”收敛;
  • 生成类操作默认要求人工确认,比如设置一个--confirm参数;
  • AI 触发的改动全部走版本控制,PCG 图和关卡文件要能一键回滚;
  • 不在打包后的游戏里启用 Remote Control 和任何 MCP 插件。

9.2 工作流规范

团队接入时,建议把流程固定成三个角色:人负责定规则和审核,Claude Code 负责在参数空间里搜索,PCG 负责实际生成。

具体落地时:

  • 把设计约束写成项目内的规范文档,AI 每次生成前先读取;
  • 每次 AI 批量改动,生成一份“改动摘要”,记录改了哪些参数、结果如何;
  • 定期把有效的参数组合沉淀成预设,减少 AI 重复试探;
  • 让 AI 的输出落在一个独立的“实验关卡”,验证通过后再合入主关卡。

9.3 性能与版本兼容

PCG 城市生成的计算量不容小觑,全城重新生成一次可能耗时几分钟。建议利用 PCG 的局部生成能力,只对改动区域重新计算;同时把生成过程放在编辑器空闲时执行。版本兼容上,UE 5.x 的 Python API 和 Remote Control 格式都有过调整,接入脚本务必标注目标版本,并且在升级引擎后先跑一遍回归测试。

9.4 后续可以深入的方向

这套 MCP + Claude Code + PCG 的架构,真正有价值的地方在于它建立了“AI 操作 UE”的标准通道。下一步可以尝试的方向包括:

  • 接入多模态能力,让 AI 读取视口截图后做视觉反馈;
  • 把建筑样式的选择做成 PCG 属性预设库,AI 按风格关键词切换;
  • 在 MCP 工具层加入批量任务队列,让 AI 并行尝试多组参数组合;
  • 用大模型自动生成 PCG 子图,再交由人工审核。

城市生成的“最后一公里”仍然是人的审美判断,但 AI 已经把到达这最后一公里的时间大幅缩短了。建议先跑通本文的最小链路:一个 MCP Server、一套白名单工具、一个 PCG 城市示例关卡。当你看到 Claude 在几分钟内替你完成十几轮参数试探时,就会理解这套工作流真正的效率价值在哪里。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进