05 · 程序化资产生成(PCG)
05 · 程序化资产生成(PCG)
程序化在独立游戏里只有三种合法用途:省钱、玩法、惊喜。 为了"酷"而做程序化,是独立游戏最烧钱的自杀方式之一。
1. 先问:你为什么需要程序化?
| 动机 | 判断 | 建议 |
|---|---|---|
| 省钱(做 100 棵树太贵) | ✅ 合法 | 用散布 + 变体,不要做完整的生成系统 |
| 玩法(roguelike 关卡) | ✅ 合法 | 这是核心系统,值得投入 |
| 惊喜(涌现、意外) | ✅ 合法 | 需要精心设计约束 |
| 规模(做超大世界) | ⚠️ 危险 | 独立游戏一般不需要超大世界 |
| 因为很酷 | ❌ | 砍 |
2. 三档程序化投入(按风险递增)
| 档 | 技术 | 成本 | 风险 | 独立游戏建议 |
|---|---|---|---|---|
| A 档:参数化变体 | 材质参数、颜色变体、缩放、旋转、组合 | 极低 | 无 | 必做 |
| B 档:散布与规则 | 植被散布、碎石、按坡度/高度/曲率分布 | 低 | 低 | 强烈建议 |
| C 档:生成系统 | WFC、噪声地形、建筑生成、关卡生成 | 中高 | 中高 | 只在它是玩法时做 |
| D 档:内容生成器 | Houdini 管线、可玩的世界生成 | 高 | 高 | 一般不做 |
3. A 档:参数化变体(零风险,必做)
原理:1 个资产 + N 组参数 = N 个视觉变体。
| 参数 | 变体效果 |
|---|---|
| 颜色 Tint | 木/石/冰/金属 |
| 缩放(非均匀) | 高矮胖瘦 |
| 旋转(Y 轴随机) | 打破重复感 |
| 材质参数(磨损/湿度/苔藓/积雪) | 年代感、地域感 |
| 部件组合(头 A + 身 B + 武器 C) | 组合爆炸 |
| 顶点色扰动 | 表面变化 |
| 细节贴图切换 | 表面材质变化 |
重复感破解三招(散布时务必用上):
- 随机 Y 轴旋转(最便宜)
- 非均匀缩放(0.9–1.1)
- 颜色/材质参数微扰(±5%)
独立游戏几乎不需要"做更多资产",只需要"让已有资产看起来不重复"。
4. B 档:散布与规则(强烈建议)
散布规则库
| 规则 | 用途 | 实现 |
|---|---|---|
| 坡度 | 岩石长在陡坡,草长在缓坡 | slope = dot(normal, up) |
| 高度 | 雪线以上有雪,水边有芦苇 | 世界 Y |
| 曲率 | 凸起处长苔,凹陷处积水 | 曲率贴图/计算 |
| 遮罩 | 手工画的区域遮罩(路径无草) | 顶点色/纹理遮罩 |
| 密度噪声 | 自然的不均匀分布 | Perlin/Simplex |
| 排斥 | 物件之间最小距离 | Poisson Disk 采样 |
| 朝向 | 朝向路径/水源/太阳 | 规则向量 |
| 生态 | 树周围长灌木不长草 | 层级规则 |
散布实现要点
- 必须烘焙成实例/合并网格,不要运行时保留几千个 GameObject
- 用 GPU Instancing
- 提供"重新随机"(Re-seed)按钮——美术会用它刷到自己满意为止
- 提供笔刷擦除——艺术家必须能手动覆盖程序化结果
- LOD + 剔除必须配套,散布最容易炸 DrawCall
散布预算
| 项 | Low | Mid |
|---|---|---|
| 同屏散布实例数 | 3000 | 10000 |
| 散布种类 | 5–8 | 10–15 |
| DrawCall 贡献 | < 50(靠 instancing) | < 100 |
5. C 档:生成系统(只在它是玩法时做)
常见算法与适配
| 算法 | 用途 | 复杂度 | 独立游戏适配 |
|---|---|---|---|
| 噪声(Perlin/Simplex/Worley) | 地形、纹理、密度、云 | 低 | ✅ 常用 |
| Poisson Disk | 自然散布点 | 低 | ✅ 常用 |
| 元胞自动机 | 洞穴、腐蚀、生长 | 低 | ✅ 常用(洞穴生成经典) |
| L-System | 植物、分形 | 中 | ⚠️ 少用(不如手做) |
| WFC(波函数坍缩) | 从样本生成布局 | 中高 | ⚠️ 谨慎(可控性差) |
| BSP / 房间图 | 地牢布局 | 中 | ✅ roguelike 常用 |
| Marching Squares/Cubes | 等值面、洞穴平滑 | 中 | ⚠️ 谨慎 |
| Voronoi / Delaunay | 区域划分、生物群系 | 中 | ✅ 有用 |
| 语法生成(Grammar) | 建筑、任务 | 高 | ❌ 一般不做 |
生成系统的五条铁律(血泪)
- 必须种子化:同一个种子必须生成完全一样的结果。否则无法复现 bug。
- 必须可手改:生成后艺术家能手动调整,且调整不被下次生成覆盖(用"覆盖层"机制)。
- 必须有确定性顺序:随机数调用顺序不能依赖帧率/线程。
- 必须有失败兜底:生成失败时回退到手工关卡,不能卡死加载。
- 必须有可视化调试:能画出生成过程的中间状态。
最常见的死法:"程序化生成的关卡偶尔会出不可通关的布局"。 解法:生成后跑可解性验证(BFS/可达性检查),失败就重生成(最多 N 次,否则回退到保底布局)。
可解性验证清单
- 起点到终点可达
- 所有必需道具可达(或在获得能力后可达)
- 无孤立区域(或孤立区域有意为之且无奖励)
- 关键路径宽度足够(角色可通过)
- 无物件卡住通道
- 刷怪点不在墙里 / 不在玩家出生点
- 无重叠的房间
6. D 档:Houdini / 大型生成管线(一般不做)
什么时候值得:
- 你的招牌就是"程序化的世界"(如 Teardown 的体素、Noita 的像素模拟)
- 你有专职 TA 且项目 > 18 个月
- 资产量确实大到手工不可能
什么时候不值得:
- 团队 < 5 人
- 只是为了"看起来专业"
- 没有 Houdini 经验但打算现学(学习曲线 6–12 个月)
折中方案:不买 Houdini,用引擎内置的 PCG 框架(UE5 PCG、Unity 的 Procedural 工具、Godot 脚本)做轻量版。
7. 程序化与美术主权(最容易被忽视的政治问题)
美术通常讨厌程序化,因为"它抢走了我的控制权"。 TA 的正确做法:
| 做法 | 说明 |
|---|---|
| 程序化产出的东西永远可手改 | 生成 → 烘焙成资产 → 美术可编辑 |
| 参数暴露给美术 | 滑杆而不是代码常量 |
| 提供 Re-seed 按钮 | 让美术"抽卡"到满意 |
| 提供笔刷覆盖 | 局部手工覆盖程序化 |
| 明确边界 | "这片区域程序化,那片手工" |
铁律:程序化是美术的助手,不是美术的替代品。 一旦美术觉得被替代,他会抵制,你的系统就废了。
8. 程序化纹理与材质
| 技术 | 用途 | 成本 |
|---|---|---|
| Substance Designer(程序化材质) | 可平铺材质 | 中(学习曲线) |
| Substance 参数化(.sbsar) | 运行时变体 | 中 |
| 噪声 + Shader 合成 | 免纹理的表面变化 | 低 |
| 顶点色驱动混合 | 地表混合(草/土/石) | 低 |
| 三平面 + 高度混合 | 免 UV 地表 | 低 |
| 运行时绘制(雪/泥/脚印) | 交互痕迹 | 中 |
| Decal 投影 | 痕迹、涂鸦 | 低 |
独立游戏建议:不需要 Substance Designer 也能做程序化材质——用3–5 张噪声贴图 + Shader 混合就能做出大部分效果,成本更低且更可控。
9. 程序化的性能陷阱
| 陷阱 | 症状 | 解法 |
|---|---|---|
| 运行时生成卡顿 | 掉帧/加载慢 | 预生成 + 烘焙;或分帧生成 |
| 实例太多 DrawCall 高 | Instancing + 合并 + LOD | |
| 生成结果未合并 | 几千个 GameObject | 烘焙为静态批次 |
| 每次进场景重新生成 | 加载慢 | 缓存生成结果(按种子存文件) |
| 内存随生成增长 | 泄漏 | 回收旧区块 |
| 生成不确定 | 回放/联机不同步 | 固定种子 + 固定调用顺序 |
10. 投入决策表
| 你的情况 | 建议 |
|---|---|
| 3D 场景需要填充植被/碎石 | B 档散布工具(1–3 人天) |
| 需要很多敌人/道具变体 | A 档参数化(0.5–1 人天) |
| Roguelike 关卡 | C 档:房间图 + 可解性验证(5–15 人天,是核心系统) |
| 开放世界地形 | C 档:噪声地形 + 散布(5–10 人天) |
| 想做"程序化城市" | 先问这是不是玩法。不是 → 砍 |
| 想学 Houdini | 除非有 6 个月以上空窗期,否则不要 |
11. 自检清单
- 程序化的动机是省钱/玩法/惊喜中的哪一个?说不出 → 砍。
- 结果可复现吗?(种子化 + 确定性)
- 美术能手动覆盖吗?
- 生成结果烘焙了吗?(不是运行时保留几千对象)
- 用 Instancing 了吗?
- 有可解性验证吗?(如果生成的是关卡)
- 有失败兜底吗?
- 有可视化调试吗?
- 参数暴露给美术了吗?有 Re-seed 按钮吗?
- 性能测过吗?(生成耗时 + 运行时开销)
- 关掉程序化,游戏还能做出来吗?能 → 说明它不是必需的,考虑简化。
12. 一句话总结
独立游戏的程序化,90% 的价值在 A 档(参数化变体)+ B 档(散布规则), 这两档风险为零、成本极低、收益立竿见影。 C 档以上只在"它本身就是玩法"时才做。 记住:程序化的目的不是"让电脑做资产",是"让美术不必重复劳动"。