
做了好几年程序化内容生成PCG我越来越确信一件事传统PCG管线最贵的地方根本不是生成算法本身而是“让所有人都能理解生成逻辑”这个环节。节点图堆得越复杂、参数暴露得越多美术同事越不敢碰技术美术TA越不敢改。最近我在一条实验性的美术生产管线里同时引入了Claude和Codex让两个AI Agent分别承担不同的角色把整条管线从“参数驱动”改成了“意图驱动”。这篇文章就聊聊这条路具体怎么走通的——适合手里有美术资产生成流程、想用大模型Agent改造管线的TA、程序化生成工程师以及被HDA和Python脚本折磨过的美术技术负责人。1. 传统PCG管线的天花板不是算法稀缺而是约束与交接成本1.1 生成器写出来只是第一步维护它才是无底洞做过PCG的人都有这种体验第一版生成器往往写得很快难的是后续迭代。美术说“这个石块太圆了”你打开Houdini找到那个控制圆度的节点调了VEX里的噪声权重然后发现旁边另一个节点的参数也跟着变了你修好了圆度美术又说“分布太均匀了要更自然一点”你又去调散射密度结果连带着把碰撞检测也触发了。这种连锁反应的本质是PCG管线的参数空间太大了而维护者通常只有一两个人。节点图本身并不难读难读的是节点背后隐含的约束关系——哪个参数控制什么、哪个值域是安全的、哪个参数组合会产生无效资产。这些信息通常只存在于写代码的TA脑子里一旦人员变动或者时间隔得久一点管线的“可维护性”就断崖式下跌。更麻烦的是美术团队不读节点图。他们只看得懂“滑块”和“预览结果”。所以传统管线的交接成本非常高程序化生成工程师要把自己的生成逻辑翻译成美术能理解的参数面板美术要把自己的审美诉求翻译成TA能落地的技术约束。这两层翻译之间信息损耗极其严重。1.2 AI Agent补上的恰恰是“意图”这一层用Claude和Codex搭管线之前我的思路一直是“怎么把节点图做得更清晰、参数面板做得更合理”。但实际跑下来我发现方向错了——参数面板做得再合理也是在语义的底层打转。真正应该改的是交互模式让美术直接用自然语言描述意图让AI去理解意图、拆解约束、生成实现。比如美术说“我需要一批荒废建筑的碎石堆部分石块要埋在土里表面风化程度不一致”。传统流程里这句话先要翻译成“碎石密度0.3~0.6”“风化噪声频率0.8”“埋藏深度偏移区间”等等参数——而这正是LLM最擅长的翻译任务。Claude在这里扮演的角色是“约束提取器”和“设计评审”它把一段模糊的视觉描述转化成结构化的生成约束Codex扮演的是“实现器”它根据约束文件去生成对应的生成器代码、批量处理脚本和自动化测试。两者合在一起PCG管线的重心从“维护生成器代码”转移到了“维护意图约束文档”而这个文档恰好是美术和TA都能看懂的。2. Claude与Codex在管线里的角色划分谁做设计谁写实现2.1 分工总览我最初的想法很简单让Claude负责所有事情。但很快发现不行——Claude在语义理解和视觉判断上很强但在“多文件改动、长链路执行、反复跑测试”这类任务里效率不如专门的代码执行Agent而Codex能连续改十几个文件、跑自动化验证但让它去理解“这种碎石分布是否符合概念设计氛围”就非常勉强。所以最后的分工是这样的任务类型Claude承担的角色Codex承担的角色意图理解与约束拆解主负责输出结构化约束清单不参与生成器方案设计主负责输出节点图结构和技术选型建议辅助实现代码生成含VEX、Python、HDA脚本审查不直接写落地代码主负责按约束文件生成实现批量测试与回归验证定义测试用例和验收标准主负责执行测试、修复失败用例渲染结果审查主负责看渲染图并输出问题标签不参与资产元数据整理与命名合规输出规范按规范实现命名工具这个表格其实是我踩了两周坑之后才定下来的。一开始我把所有事都丢给同一个Agent做上下文一长它就会在“生成代码”和“审查代码”两个角色之间来回漂最后既没写好代码也漏审了问题。把角色拆开之后每个Agent只做自己最擅长的事互相检查整个链路的稳定性反而上来了。2.2 为什么需要两个Agent而不是一个有人会问用同一个模型的两次调用设定两个system prompt不就行了吗为什么非要Claude加上Codex两个不同的工具我的实际体会有三点。第一失败模式互补。同一个模型容易在同一类问题上反复出错——比如它在生成节点代码时忘了连某个输入端口你让它自己审查它大概率依然会漏掉同一个端口。而不同模型的注意力分布不一样让Claude从“设计意图是否在代码中体现”的角度审查Codex的产出物更容易挑出结构性问题。这种审查不是“找语法错误”而是“验证代码和约束的一致性”。第二执行环境隔离。PCG管线的代码生成往往涉及实际运行Codex可以直接在沙箱里跑Houdini的命令行模式生成资产并输出日志而Claude更适合做不依赖执行环境的分析工作比如读节点图的导出文本、看渲染缩略图。把执行和审查分开能避免Agent一边改代码一边判断结果导致的“自我验证失效”。第三上下文管理更清晰。Codex工作时的上下文是“代码仓库错误日志”Claude工作时的上下文是“需求描述设计文档渲染图”。两者各维护一套独立上下文不会互相污染。这也是后面我会讲的“约束文件”策略的前提。2.3 一条完整的协作闭环怎么跑实际工作中我的管线跑起来大概是这样的流程美术在文档里写下一段需求描述例如“雨后的鹅卵石路面石板之间有苔藓局部破损”。Claude读取需求拆解出资产域、数理约束、风格标签输出一份JSON格式的约束清单。Codex读取清单在基础生成器框架里生成对应参数和节点代码并运行自动化测试。管线批量生成一批资产预览图连同资产元数据一起输出。Claude逐张看预览图对照约束清单和参考图标记问题比如“第三批次石块棱角过锐不符合磨损描述”。问题标签回传给Codex修正生成器中的权重或噪声参数重新生成并再次验证。这个过程里Claude和Codex并没有直接对话它们之间唯一的交流介质就是“约束文件”和“问题标签”。这个设计很关键如果让两个Agent直接对话它们很容易在协商过程中偏离初始需求而且日志不可追溯。用文件和标签作为接口整个流程像是流水线上两道工序每一道都可以单独验证。3. 从零搭一条“意图驱动”美术管线的五个落地步骤3.1 步骤一资产域建模把美术资产拆成语义参数这一步是纯人肉工作也是整条管线的地基。目标是把要生成的美术资产拆成“语义参数”而不是“原始参数”。两者的区别在于原始参数是“噪声频率0.8、位移强度1.5”语义参数是“风化程度、破损密度、苔藓覆盖率”。我以“废弃建筑落石堆”为例最后拆出来的语义参数大概是这样的碎石密度控制单位面积内石块数量取值范围低中高埋藏程度石块与地面/土层的相对深度关系风化程度表面细节的磨损和钝化程度分布均匀度倾向自然随机还是人工堆积颜色变化幅度灰度/色相的波动区间拆完语义参数之后还要定义每个参数的量纲和范围。注意这里不要直接写具体数值而是先写语义描述等到Claude生成约束文件时再由它补上默认数值和合理区间。如果一开始就把数值定死等于又回到传统参数面板的老路上了。这一步还有个容易被忽略的事定义“不可变约束”。比如“所有资产必须能通过碰撞检测”“单个资产三角面数不超过8000面”“UV不能跨象限”。这些约束和美术意图无关是技术底线必须单独列出来后续会写进约束文件的最高优先级区域。3.2 步骤二让Claude做约束枚举与冲突检测资产域建模完成之后把语义参数清单和技术底线一起提交给Claude让它做两件事第一补全遗漏的约束第二检测约束之间是否存在冲突。我通常会这样写Prompt以下是某项目的落石堆资产语义参数清单。请完成两件事 1. 基于你的视觉设计经验补充你认为对“废弃建筑落石堆”至关重要的、但清单里缺失的参数。 2. 检查当前参数之间是否存在冲突例如“大量埋藏”和“高风化度”是否会互相排斥。 请用JSON输出最终约束清单每个参数必须包含参数名、语义描述、数据类型、默认值、最小/最大建议值、与哪些参数存在耦合。Claude在这里的价值是“经验补全”。比如它会提醒你“深层埋藏”可能使“表面苔藓覆盖率”失去意义因为被埋住的岩石表面本来就看不到苔藓它还会建议把“分布均匀度”改为逻辑枚举而不是连续数值因为美术对这个参数的感知本来就是离散的。冲突检测非常重要。传统管线里这种冲突通常是在美术调参调崩了之后才暴露出来而现在能在设计阶段就规避掉。Claude输出的JSON就直接作为约束文件后面所有环节都以这个文件为准。3.3 步骤三让Codex读取约束文件生成生成器与循环测试约束文件落地之后就是Codex的主场。我给它设定明确的任务边界读取约束JSON在已有的生成器框架里实现对应逻辑并且必须配套生成一个回归测试脚本。一个典型的任务描述是这样的请读取constraints.json在generator_template.py的基础上实现落石堆生成逻辑。 要求 - 每个语义参数必须映射到具体的生成函数 - 参数值在约束文件边界之外时进行钳制并输出警告日志 - 回归测试test_smoke.py必须覆盖极端值参数组合、空输入、约束冲突时抛错 - 不允许修改约束文件本身Codex会生成类似这样的核心代码这里只展示结构不是完整实现def generate_rock_pile(params): density params.get(density, medium) burial params.get(burial, low) weathering params.get(weathering, medium) rock_count resolve_density(density) distribution resolve_distribution(params.get(uniformity, natural)) rocks instantiate_rocks(rock_count, distribution) if burial deep: rocks apply_burial(rocks, amount0.8) if weathering high: rocks apply_weathering(rocks, intensity0.95) validate_mesh_constraints(rocks) return rocksCodex在跑这一步的时候我观察到的最大好处是它会把“测试和实现一起写”。这非常关键因为传统人工写生成器的时候写测试往往是最后补的甚至直接不写。而Codex作为代码Agent天然倾向于用测试来验证自己写出的代码没问题——这恰好补上了PCG管线里最容易缺失的“回归安全网”。3.4 步骤四批量烘焙与预览接入生成器代码通过回归测试之后就要接入实际的批量生产环境。这一步我自己写了一个调度脚本在DCC软件的命令行模式下跑把生成结果批量烘焙成预览缩略图同时输出一份资产元数据表。缩略图的输出目录结构是这样的output/ batch_001/ assets/ rock_001.obj rock_002.obj previews/ rock_001_front.png rock_001_side.png metadata/ batch_001.jsonmetadata里的内容包括每个资产的生成参数快照、约束文件版本号、生成器commit号。这些在后续排查问题和版本比较时非常有用。关键细节预览图一定要多角度输出。我一开始只生成俯视图结果很多问题根本看不出来——比如石块之间的穿插从俯视角度看会被遮挡侧面视角才暴露。后来改成前视、侧视、透视三个角度Claude审查的准确率明显提升。3.5 步骤五建立“渲染图审查→参数修正”的闭环管线跑起来之后最重要的是把Claude接入最后的审查环节。我写了一个审查Prompt结构基本固定以下是某批次落石堆资产的预览图共9张。请对照约束文件要求逐张检查并输出问题标签。 问题标签格式要求[问题类别] [严重程度] [涉及参数] [建议修正方向]。 需要重点关注石块穿插、比例失调、分布过于规则、表面细节与风化程度不匹配、明显违反技术底线如穿插不可修复。Claude的审查结果会以JSON形式回传比如{ issues: [ { asset_id: rock_004, category: intersection, severity: 2, params: [burial], suggestion: 降低burial到medium减少石块与地层的穿插 } ] }这些标签会被自动合并到下一轮Codex的任务描述里。整个过程不需要人工翻译自然语言问题标签既是给Codex的修改指令又是团队可以阅读的审查记录。相当于每个生成批次都有了“机器可读人可读”的质检记录。4. 跑通之后踩过的四个真实坑点4.1 代码能生成但DCC节点依赖经常出错第一个坑来自Codex它生成的Python代码单独拎出来看完全没问题但放进DCC环境里就报错。排查了半天发现代码里调用的某个节点类的实例化方式在新版本里已经换成新API了而Codex根据训练数据下意识地用了老写法。这个问题的根本原因在于代码Agent不了解“当前DCC软件版本下的节点依赖关系”。它的知识是通用的不是针对你这个具体环境的。我的解决办法是两步第一在Codex的任务描述里固定附上当前DCC版本号和关键API差异说明这就相当于给它一份“环境知识卡”第二让Claude去审查Codex产出的节点图导出文本DCC软件可以把节点网络导出成文本描述从“节点连接是否符合逻辑”的角度检查而不是从“API是否存在”的角度检查。两个模型各管一层错误率大幅下降。4.2 不看渲染图数值审查全是隔靴搔痒第二个坑是我一开始没让Claude看渲染图只让它基于数值输出审查结论。结果很惨——它说“建议降低风化度以保留更多表面细节”但实际渲染图里风化度已经很低了问题出在UV拉伸上和风化度根本没关系。这让我意识到PCG资产的很多问题是视觉结构问题不是数值参数问题。不看到像素级的渲染结果再聪明的模型也没办法发现问题。后面我强制改成“每批次资产必须附带预览图才能进入审查环节”并且给Claude的输入里加了一条规则先描述你对每张图观察到的视觉特征再输出问题标签。这一条规则让审查报告的质量上了一个台阶因为它强迫模型在“看图”和“判断”之间做了显式推理而不是靠猜。4.3 参数范围幻觉导致整批资产作废第三个坑更隐蔽Claude在补全约束文件时“拍了脑袋”写出了一组参数范围。比如它给“苔藓覆盖率”写了0到1的区间看起来合理但生成器执行时发现这些数值被直接映射成了纹理混合度0.5的实际视觉覆盖率比预期的“中等覆盖”低了很多。结果一整批资产看起来都像只长了稀疏的几簇苔藓。这个问题的根源是LLM对“参数物理量纲”的感知是模糊的。它知道“苔藓覆盖率”应该在0到1之间但它不知道你的生成器里0.5具体对应什么视觉密度。修正方法是任何语义参数生成器里的默认值都必须由人工指定或者通过至少一轮“渲染对照实验”来校准。我专门做了一个小实验把每个语义参数从最小值到最大值生成五个梯度版本人工确认哪一档符合“低中高”的语义再把映射关系写回约束文件。这个过程只需要做一次之后Claude和Codex就有了统一的“语义-数值”坐标系不会再乱来。4.4 上下文一长Agent就忘了最初的设计约束最后一个坑是关于Agent本身的长时间工作流里Codex会逐渐“漂移”——它一开始严格按照约束文件写代码但改了几轮问题之后开始“自由发挥”把约束文件的某些字段改名了甚至加了约束文件里根本不存在的参数。这不是幻觉是上下文太长导致的注意力稀释。最初的约束文件被后续的修改日志逐渐“冲淡”了模型在生成新代码时更关注最近几轮对话而对最开始的约束敏感度下降。我的解决方案非常朴素把约束文件设置成“单一事实来源”每次任务开始时重新读取一次并且Prompt里写死一条规则当你的修改与约束文件冲突时以约束文件为准并且明确标注冲突位置。Codex改完代码后还会让它输出一份“本次修改与约束文件逐条对应清单”没有对应关系的变更直接拒绝。这样就像给Agent加了一条强制审计链漂移问题基本被治住了。5. 工程化落地时要提前想清楚的事5.1 资产版本管理与回归基线的位置把AI Agent引入PCG管线之前我低估了版本管理的重要性。传统流程里生成器版本管理的是代码现在约束文件、生成器代码、审查标签、基准资产库——四样东西必须同时纳入版本管理。我的做法是把它们放同一个仓库用一次commit代表一次完整迭代。commit message写成这样feat: 调整落石堆的风化度映射 - 修改constraints.json中weathering的默认值区间 - 更新generator_rock_pile.py中的映射逻辑 - 新增batch_017作为新基线 生成结果对比: 较batch_016穿插问题减少70%苔藓覆盖更符合预期为什么要强调“回归基线”因为PCG管线的最大风险是“修好一个资产坏掉十个资产”。没有基线资产库你根本不知道一次改动影响了哪些批次。我每次迭代都会让管线自动跑一批基线资产然后对比生成结果的缩略图差异差异过大的批次会直接标记为“疑似回归”交给Claude进一步审查。这一步把很多潜在问题拦截在提交之前。5.2 让美术同事信任AI生成结果技术上的问题都能解决团队协作反而是难点。美术同事一开始对Agent生成的资产很不信任觉得“这不是我调的我不敢用”。我后来做了一个很有效的改动把Claude的审查标签可视化。每一张预览图旁边直接叠加上一个问题标签列表比如“穿插风险高”“棱角过锐”“苔藓分布不均”。美术同事看到的不只是“AI说有问题”而是“AI说这个资产哪里有问题”。更重要的是每个标签都会附带“建议调整方向”美术觉得不对可以直接改参数重新生成而不是被迫接受。另外一个值得做的事是给每个资产加上“生成解释”。元数据里记录了“这个资产为什么长这样”——用了哪些语义参数、哪些约束被激活了。这让美术同事能看懂生成结果背后的逻辑而不是把AI生成物当成一个黑盒。信任是慢慢建立的透明化是建立信任的唯一路径。5.3 与现有引擎、DCC工具的接缝处理最后聊一下接缝问题。一套AI驱动的PCG管线最终还是要落到美术团队日常使用的软件里。我的经验是不要在Agent和美术工具之间做太深的耦合。具体来说Agent产生的中间产物约束文件、问题标签、审查报告全部是独立于DCC软件存在的。生成器只在需要时通过命令行被调度执行输出标准格式的资产文件如通用三维模型格式。美术团队照常用他们熟悉的软件导入这些资产他们根本不需要关心这些资产是哪一步AI生成出来的。这个设计的好处是任何DCC软件升级、更换、甚至迁移到下一代引擎环境管线的核心逻辑都不受影响。换的只是最后一公里的导入导出适配层。PCG管线本身是长期的资产不要让它的生命周期被单一工具版本绑定。最后分享一个实际操作中的体会如果你也想用Claude和Codex搭自己的美术生产管线我的核心建议是不要让Agent直接生成最终资产而是让Agent生成“生成最终资产的系统”。你维护的是一段可重复的生成逻辑和一份清晰约束文档而不是一批一次性资产。我一开始总想让AI直接给我产出满意的模型文件后来发现这个方向会让Agent陷入无限试错的泥潭而当我把它改成“用Agent改进生成器”每一轮迭代的成果都可以沉淀下来资产质量和团队效率才真正开始向上走。这条路走下来需要一点耐心但回报是值得的。