1. 从 Fireside 场景说起:PCG 里 StaticMesh 与 Level Brush 到底怎么配合
如果你最近在 Unreal Engine 5 里打开过 Content Examples 的 PCG 示例关卡,大概率会看到类似这样的结构:一个 Persistent Level 叫Fireside,下面挂着一个子 LevelL_BaseEnvironment,Viewport 右下角常驻一个 Current Context 浮层,告诉你当前选中的 Actor 属于哪个 Level、新建 Actor 会写进哪个 Level。再往里看,PCGVolume上挂着一个BrushComponent0,执行 Graph 之后组件树里冒出一串ISM_PCG_Cube_8、ISM_PCG_Cube_9。这套东西第一次看确实容易懵:StaticMesh 是网格,Level 是地图,Brush 是老式几何体,它们怎么在 PCG 工作流里凑到一起的?
这篇就按“配置 + 验证”的路子走一遍。核心检索词先摆出来:Unreal Engine PCG 中 StaticMesh 与 Level Brush 的配置与验证,适合正在搭关卡、做程序化生成、被 PCGVolume 边界和 ISM 输出搞晕的人。我会把 PCG Graph 节点配置、StaticMesh 与 Brush 参数、逐步验证动作都写成可复制的形式,你在自己项目里能直接对照。
先说清楚三者的角色分工,不然后面配置会乱。StaticMesh 是最终被实例化出来的可见几何体,PCG 通过 Static Mesh Spawner 节点把点数据变成 ISM 实例。Level Brush 这里有两层含义:一是PCGVolume内部那个BrushComponent,它定义 PCG 的采样/生成空间边界;二是传统 Geometry Brush 体系里的 BSP/Volume 几何表示,PCGVolume 沿用了这套老类型。Level 则是编辑上下文,决定你新建的 Actor 写进Fireside.umap还是L_BaseEnvironment.umap。
我试过在一个展示环境里把基础环境、灯光、角色展示拆成三个 Sublevel,PCG 生成物单独放一个 Level,结果排查问题时定位快很多。下面按步骤来。
2. TaoToken 前置:给 PCG 调试配一个稳定的模型对话入口
PCG Graph 调参过程中经常需要查节点语义、对报错、让模型帮你解释一段 Graph 逻辑。我习惯在旁边开一个模型对话窗口,遇到Discard Points on Irregular Surface这种节点不确定行为时直接问。这里用 TaoToken 做接入,官网 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,API 地址 https://taotoken.net/api 。
先拿 Key。进控制台 https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_content=console&utm_campaign=rewrite ,在 API Keys 页面 https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api-keys&utm_campaign=rewrite 创建一个新 Key,复制出来。注意这个 Key 只在创建时完整显示一次,丢了就重建。
模型对话入口在 https://taotoken.net/chat?utm_source=taotoken_aicg_blog_end&utm_content=model_chat&utm_campaign=rewrite ,可以直接在里面问 PCG 节点问题。如果你要长期做编码和 Agent 类任务,Coding Plan 在 https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding_plan&utm_campaign=rewrite 。接入文档在 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite 。
这一步不是必须,但 PCG 调试时有个能随时问的模型窗口,比反复翻文档快。Key 拿到后先放着,下一节配置里会用到。
3. 可复制配置:PCG Graph 节点、StaticMesh 参数与 Brush 设置
这一节是重点,配置片段都能直接抄。先建 PCG Graph,再配 PCGVolume,最后接 Static Mesh Spawner。
3.1 PCG Graph 基础节点链
在 Content Browser 右键 → PCG → PCG Graph,命名PCG_FlatnessSpawn。打开 Graph,按下面顺序连节点:
Get Landscape Data → Surface Sampler → Discard Points on Irregular Surface → Static Mesh SpawnerSurface Sampler的 Points Per Squared Meter 先设 0.5,调试阶段别设太高,不然点太多卡编辑器。Discard Points on Irregular Surface的关键参数是 Flatness Tolerance,默认 0.1,意思是法线偏差超过这个阈值的点被丢掉。你要检测“足够平”的表面,就把它调到 0.05 到 0.15 之间试。
Static Mesh Spawner里指定 Mesh Entry,选你的 Cube 或任意 StaticMesh。这里有个容易踩的点:Mesh Entry 的 Weight 和 Scale 如果留默认,生成出来可能大小不一。调试时先把 Scale 固定成 (1,1,1)。
3.2 PCGVolume 与 BrushComponent 配置
把 PCGVolume 拖进关卡,选中它,Details 面板里找到 Brush Settings。Brush Type 选 Additive,Solidity 选 Solid。这个 BrushComponent 就是 PCG 的采样边界,Graph 只在这个体积内跑。
如果你想改边界形状,在 Brush Settings 里改 Brush Shape,或者用 Geometry 编辑模式直接拖。注意 BrushComponent 是 Inherited 的,不能删,但 Transform 和 Brush Settings 可以改。
3.3 编辑上下文与 Level 归属
Viewport 右下角那个 Current Context 下拉框,决定新建 Actor 写进哪个 Level。当前是Fireside (Persistent)和L_BaseEnvironment两个选项。你要把 PCG 生成物单独管理,就先在 Levels 窗口新建一个 Sublevel,命名L_PCG_Output,然后把它设为 Current Context。
Levels 窗口里蓝色名称代表 current level。设好之后,你拖进去的 PCGVolume 和它生成的 ISM 组件都会写进L_PCG_Output.umap,不会污染主 Level。
3.4 一份可直接用的 settings 片段
如果你用命令行或脚本批量配置,参考这个 JSON 结构(字段名对应 UE 资产属性):
{ "PCGGraph": "PCG_FlatnessSpawn", "PCGVolume": { "BrushType": "Additive", "Solidity": "Solid", "ActorLevel": "L_PCG_Output" }, "SurfaceSampler": { "PointsPerSquaredMeter": 0.5, "ActorFilter": "Landscape" }, "DiscardPoints": { "FlatnessTolerance": 0.1 }, "StaticMeshSpawner": { "MeshEntry": "/Game/Meshes/SM_Cube", "Scale": [1.0, 1.0, 1.0] } }路径按你项目实际改。这份配置对应的是“在平坦表面上按密度撒点,丢掉不平的点,再实例化成 Cube”的完整链路。
4. 验证请求与成功结果:怎么确认配置真的生效
配完不算完,得验证。分四步。
第一步,选中 PCGVolume,Details 里点 Generate。如果 Graph 没问题,Viewport 里会出现一批 Cube。同时组件树里会多出ISM_PCG_Cube_8这类组件。看到 ISM 组件就说明 Static Mesh Spawner 正常工作了。
第二步,检查点数据。在 PCG Graph 里选中Discard Points on Irregular Surface节点,开启 Debug 显示,Viewport 里会用不同颜色标出保留和丢弃的点。平坦区域点保留,斜坡上的点变红被丢。这一步能直观确认 Flatness Tolerance 设得对不对。
第三步,确认 Level 归属。在 Levels 窗口看L_PCG_Output是否被标记为 current,然后在 World Outliner 里选中一个 ISM 组件,Viewport 右下角浮层应该显示Selected Actor(s) in L_PCG_Output。如果显示的是Fireside (Persistent),说明你 Current Context 没切对,生成物写进主 Level 了。
第四步,验证 Brush 边界。把 PCGVolume 的 Brush 缩小一半,重新 Generate,Cube 应该只在缩小后的体积内出现。如果体积外还有 Cube,检查是不是有多个 PCGVolume 或者 Graph 里用了全局采样。
成功结果长这样:Viewport 里 Cube 整齐分布在平坦表面,斜坡和凹凸处没有实例;组件树里 ISM 组件数量与 Mesh Entry 种类对应;Levels 窗口里生成物归属正确;重新 Generate 时旧实例被清理、新实例生成,没有残留。
5. 本篇常见错排查:401、local proxy failed、reading choices、OAuth
配置和验证过程中,报错集中在几类。逐个对。
401 Unauthorized:如果你在 PCG 调试时用模型对话查问题,Key 配错会报 401。检查 API Key 是否完整复制,Base URL 是否写成https://taotoken.net/api,注意不要多加斜杠或路径。Key 泄露或过期就重建。
local proxy failed:本地代理类工具连不上时常见。检查你的网络配置是否指向了正确的 endpoint,Base URL 和 Key 是否匹配。如果是 Claude Code 类工具,确认ANTHROPIC_BASE_URL和ANTHROPIC_API_KEY都设对了。
reading choices 报错:模型返回结构解析失败,通常是请求体格式不对。检查你发的 JSON 是否符合 OpenAI 兼容格式,model字段是否填了有效 Model ID。PCG 调试场景下用模型对话时,确认选的模型支持你要问的内容。
OAuth 相关报错:如果你用 Claude Code 或类似工具,OAuth 流程没走完会报错。确认回调地址、client 配置正确。用 API Key 方式接入通常能绕过 OAuth 问题。
PCG 侧常见错:Generate 后没有 Cube,先看 PCGVolume 的 Brush 是否覆盖了 Landscape;再看 Surface Sampler 的 Actor Filter 是否匹配;最后看 Discard 节点是否把点全丢了,把 Flatness Tolerance 调大试试。ISM 组件不出现,检查 Static Mesh Spawner 的 Mesh Entry 是否为空。
Level 归属错:生成物写进了错误的 Level,回 Levels 窗口把目标 Sublevel 设为 current,重新 Generate。已经写错的 Actor 可以手动拖到正确 Level,或者在 World Outliner 里 Cut 再 Paste 到目标 Level。
6. 语义一致 CTA:把 PCG 调试链路固定下来
PCG 工作流里 StaticMesh、Level Brush、编辑上下文这三样东西,配一次容易,长期维护靠的是固定链路。我的做法是:模型对话窗口常开,遇到节点语义和报错直接问;PCG Graph 参数用版本管理记录;Level 分层从一开始就规划好,别等生成物堆满主 Level 再拆。
需要模型对话入口的去 https://taotoken.net/chat?utm_source=taotoken_aicg_blog_end&utm_content=model_chat&utm_campaign=rewrite ,长期做编码和 Agent 任务的看 https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding_plan&utm_campaign=rewrite ,接入细节查 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite 。Key 在 https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api-keys&utm_campaign=rewrite 管理。
最后留一个实用技巧:PCG Graph 调参时,把Discard Points on Irregular Surface的 Debug 显示开着,边调 Flatness Tolerance 边看 Viewport 颜色变化,比盲调快得多。Brush 边界改完记得重新 Generate,不然看到的还是旧结果。