# 程序化内容生成(PCG)
> 从《Rogue》到《我的世界》,PCG 让无限内容成为可能。但真正的挑战不在于生成,而在于**生成有趣的内容**。
---
## 目录
1. [PCG 核心概念](#pcg-核心概念)
2. [Roguelike 与 Rogue-lite 设计](#roguelike-与-rogue-lite-设计)
3. [程序化关卡生成](#程序化关卡生成)
4. [程序化地形生成](#程序化地形生成)
5. [程序化任务与叙事](#程序化任务与叙事)
6. [PCG 与玩家体验平衡](#pcg-与玩家体验平衡)
7. [工具与引擎支持](#工具与引擎支持)
8. [经典案例分析](#经典案例分析)
---
## PCG 核心概念
### 什么是 PCG
程序化内容生成(Procedural Content Generation)指通过算法而非人工手动创建游戏内容。内容范围包括关卡、地形、任务、道具、纹理、音乐甚至叙事。
### PCG 的核心价值
| 价值 | 说明 | 典型应用 |
|------|------|----------|
| **无限重玩性** | 每次游戏体验不同 | Roguelike、生存游戏 |
| **降低开发成本** | 用算法替代大量手工制作 | 开放世界地形 |
| **动态难度适配** | 根据玩家能力调整内容 | AI Director(L4D)|
| **玩家共创** | 玩家输入影响生成结果 | 《我的世界》建筑 |
| **压缩存储** | 用种子值替代完整数据 | 《 Elite Dangerous》星系 |
### 生成方法分类
```
PCG 方法谱系
├── 基于规则(Rule-based)
│ ├── 语法系统(Shape Grammar)
│ ├── L-System(分形植物)
│ └── 替换系统(WFC - Wave Function Collapse)
├── 基于搜索(Search-based)
│ ├── 遗传算法(Genetic Algorithm)
│ ├── 模拟退火(Simulated Annealing)
│ └── 进化策略(Evolutionary Strategies)
├── 基于学习(Learning-based)
│ ├── 马尔可夫链(Markov Chain)
│ ├── 神经网络生成
│ └── GAN / Diffusion Model
└── 混合方法
├── 手工模板 + 程序填充
└── 程序生成 + 人工筛选
```
---
## Roguelike 与 Rogue-lite 设计
### 核心设计维度
| 维度 | Roguelike(柏林诠释) | Rogue-lite(现代变体) |
|------|----------------------|----------------------|
| **永久死亡** | ✅ 严格 | ✅ 通常保留部分进度 |
| **回合制** | ✅ 必须 | ❌ 常为即时 |
| **网格移动** | ✅ 传统 | ❌ 自由移动常见 |
| **随机生成** | ✅ 核心 | ✅ 核心 |
| **复杂度** | 极高(NetHack) | 适中(Hades) |
| ** meta-progress** | ❌ 无 | ✅ 解锁、升级 |
### 随机生成关键系统
#### 1. 房间-走廊地牢(Room-and-Corridor)
```
算法:随机房间放置 + 最小生成树连接
步骤:
1. 随机生成 N 个不重叠的房间(Bounding Box 检测)
2. 计算房间中心点,构建完全图
3. 用 Prim/Kruskal 生成最小生成树(保证连通)
4. 添加 10-20% 冗余边(循环路径)
5. 沿房间中心连线挖掘走廊(曼哈顿路径 + 随机转折)
6. 放置入口、出口、钥匙-门谜题
```
**参数调优表:**
| 参数 | 小型地牢 | 中型地牢 | 大型地牢 |
|------|----------|----------|----------|
| 房间数量 | 5-8 | 10-20 | 25-40 |
| 最小房间尺寸 | 3x3 | 4x4 | 5x5 |
| 最大房间尺寸 | 6x6 | 8x8 | 12x12 |
| 房间间距 | 2 | 2-3 | 3-5 |
| 循环边比例 | 15% | 20% | 25% |
#### 2. 细胞自动机洞穴(Cellular Automata)
```
初始化:随机填充 45-50% 的墙
迭代规则(4-5 次):
- 邻居墙 < 4 → 变为地板(平滑)
- 邻居墙 ≥ 5 → 变为墙
- 处理边界:始终为墙
后处理:
- 连通性检测(Flood Fill)
- 移除过小区域
- 识别并标记房间
```
#### 3. 波函数坍缩(Wave Function Collapse)
```
核心思想:基于局部约束的铺砖系统
输入:一组 tile 及其邻接规则
┌───┬───┐
│草地│草地│
├───┼───┤ → 规则:草地可邻接草地、泥土
│泥土│水 │ 水只能邻接水、泥土
└───┴───┘
执行:
1. 初始化网格:每个格子为所有可能状态的叠加
2. 选择熵最低(约束最多)的格子
3. 根据权重随机坍缩到一个状态
4. 传播约束到邻居,更新可能性
5. 重复 2-4 直到全部坍缩或矛盾
矛盾处理:回退(Backtracking)或重新初始化
```
### Roguelike 经济系统设计
| 资源类型 | 获取方式 | 消耗场景 | 设计要点 |
|----------|----------|----------|----------|
| **HP/生命** | 药水、休息、升级 | 战斗伤害、陷阱 | 紧张感核心 |
| **货币** | 击杀、宝箱、出售 | 商店购买 | 风险-回报权衡 |
| **道具充能** | 固定恢复、稀有掉落 | 使用技能/道具 | 限制最强策略 |
| **食物/饥饿** | 拾取、购买 | 时间流逝 | 推动玩家前进 |
| **经验/升级** | 击杀、任务 | 升级获取能力 | 长期进度感 |
---
## 程序化关卡生成
### 生成范式对比
| 范式 | 代表游戏 | 优点 | 缺点 |
|------|----------|------|------|
| **完全随机** | 早期 Roguelike | 无限变化 | 质量不稳定 |
| **模板组合** | Diablo 3 | 保证质量 | 重复感明显 |
| **参数化设计** | Spelunky | 可控性高 | 需要大量调参 |
| **语法生成** | Unexplored | 逻辑性强 | 实现复杂 |
| **AI 辅助** | 实验性项目 | 学习设计模式 | 训练成本高 |
### 基于块的关卡生成(Chunk-based)
```
《我的世界》地下城 → 预设计房间块 + 随机组合
块类型:
├── 入口块(固定,1个)
├── 战斗块(10+ 变体,按难度分级)
├── 解谜块(5+ 变体)
├── 奖励块(3+ 变体,隐藏入口)
├── 商店块(1-2 个,间隔出现)
├── Boss 块(固定,1个,终点前)
└── 出口块(固定,1个)
组装规则:
- 入口 → 战斗 → 战斗/解谜 → 奖励/商店 → ... → Boss → 出口
- 每个节点的出边受类型限制(战斗可接任何类型,商店后必须有战斗)
- 路径长度:8-12 个块
- 难度曲线:线性递增 + 随机波动 ±10%
```
### 关卡生成质量验证
```python
# 伪代码:关卡质量检查器
def validate_level(level):
checks = {
'连通性': flood_fill_check(level),
'可达性': all_reachable(level, ['start', 'key', 'door', 'exit']),
'难度曲线': difficulty_monotonic(level, tolerance=0.15),
'资源平衡': resources_sufficient(level, min_potions=2, min_weapons=1),
'路径多样性': alternate_paths_exist(level, min_alternatives=2),
'无软锁': no_soft_locks(level), # 不会因随机无法通关
}
return all(checks.values()), checks
```
---
## 程序化地形生成
### 噪声函数对比
| 噪声类型 | 特性 | 适用场景 | 计算成本 |
|----------|------|----------|----------|
| **Value Noise** | 简单插值,块状感 | 低要求场景 | 低 |
| **Perlin Noise** | 平滑连续,方向性 | 地形高度图、云 | 中 |
| **Simplex Noise** | Perlin 改进,低维度效率 | 3D 地形、动画 | 中 |
| **Worley Noise** | 细胞状,边缘清晰 | 石块、裂纹、蜂巢 | 中 |
| **Voronoi** | 区域分割 | 生物群系边界 | 中 |
| **Fractal Brownian Motion** | 多频段叠加 | 真实地形 | 中高 |
### 多层地形生成流程
```
《我的世界》风格地形生成流程:
1. 大陆尺度(1:16 采样)
└── 温度噪声 + 湿度噪声 → 生物群系选择
2. 地形尺度(1:4 采样)
└── 3D Perlin Noise(8 倍频)→ 密度场
└── 密度 > 0.5 → 石头,< 0.5 → 空气
3. 表面细节(1:1)
└── 地表替换:石头→泥土→草方块
└── 洞穴系统:3D Worley Noise 挖空
4. 特征放置
└── 树、矿石、结构 → 基于群系的概率分布
└── 村庄、地牢 → 结构模板 + 地形适配
5. 后处理
└── 光照计算、流体模拟、植被生长
```
### 地形参数设计
| 参数 | 取值范围 | 效果 |
|------|----------|------|
| Octaves | 1-8 | 细节层次数量 |
| Persistence | 0.3-0.7 | 高频细节强度衰减 |
| Lacunarity | 1.5-2.5 | 频率倍增因子 |
| Scale | 50-500 | 地形起伏尺度 |
| Height Multiplier | 10-200 | 垂直夸张度 |
| Seed | 任意整数 | 可复现的随机源 |
---
## 程序化任务与叙事
### 任务生成架构
```
任务 = 目标 + 约束 + 奖励 + 叙事包装
目标类型:
├── 到达(Go to X)
├── 获取(Collect N of X)
├── 击杀(Kill N of X)
├── 护送(Escort X to Y)
├── 保护(Defend X for T time)
├── 制造(Craft X using Y, Z)
└── 社交(Talk to X, persuade Y)
约束:
├── 时间限制
├── 顺序依赖(先完成 A 才能 B)
├── 互斥(A 和 B 不能同时选)
├── 状态要求(需要道具/等级/声望)
└── 环境限制(只在夜晚/雨天出现)
```
### 涌现式叙事(Emergent Narrative)
| 元素 | 手工叙事 | 涌现叙事 | 混合方案 |
|------|----------|----------|----------|
| **故事结构** | 预设三幕剧 | 玩家行为驱动 | 关键节点预设 + 路径自由 |
| **角色关系** | 固定好感度 | 动态派系系统 | 关键 NPC 固定 + 次要 NPC 动态 |
| **世界状态** | 线性章节 | 完全开放 | 区域状态机 |
| **任务链** | 精心编排 | 随机组合 | 模板 + 参数填充 |
### 《矮人要塞》叙事生成
```
世界生成流程:
1. 神话生成 → 创世神、神系、魔法规则
2. 地质历史 → 板块运动、山脉河流
3. 文明兴起 → 种族、国家、战争历史
4. 人物生成 → 历史人物、家族谱系、恩怨情仇
5. 当前状态 → 活跃势力、任务来源、冲突点
叙事钩子示例:
- "铁锤氏族的王子被龙绑架,龙要求 1000 银锭赎金"
- "精灵与矮人的百年战争因一片神圣森林的归属再次爆发"
- "一个堕落的神谕者正在招募信徒召唤古神"
```
---
## PCG 与玩家体验平衡
### 生成的内容 vs 手工设计
| 方面 | 完全手工 | 混合(推荐) | 完全程序 |
|------|----------|-------------|----------|
| **质量上限** | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐ |
| **变化性** | ⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| **开发效率** | ⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| **玩家惊喜** | ⭐⭐⭐(精心设计) | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ |
### 质量保障策略
1. **模板预验证**:所有生成模块需通过人工设计的测试用例
2. **运行时验证**:生成后立即运行质量检查(见上文 `validate_level`)
3. **玩家数据反馈**:追踪生成内容的完成率、死亡率、满意度
4. **混合编辑**:程序生成 → 人工筛选 → 玩家体验 → 算法调优
### 感知随机性
| 问题 | 现象 | 解决方案 |
|------|------|----------|
| **伪随机感** | 玩家觉得"算法在针对我" | 使用公平骰子(补偿随机) |
| **连败挫败** | 连续多次失败 | 保证 N 次内必有成功 |
| **奖励疲劳** | 稀有掉落不再兴奋 | 动态调整稀有度感知 |
| **难度跳跃** | 突然变难或变易 | 平滑难度曲线 + 偏差修正 |
---
## 工具与引擎支持
| 工具/引擎 | PCG 能力 | 适用场景 |
|-----------|----------|----------|
| **Unity** | Terrain Tools、ProBuilder、自定义 C# | 通用,生态丰富 |
| **Unreal** | PCG Framework(5.2+)、Landscape | 3A 级别地形 |
| **Godot** | OpenSimplexNoise、TileMap 自动生成 | 2D/独立游戏 |
| **Houdini** | 行业标杆,节点式程序化 | 影视级内容 |
| **MapGraph** | Unity 插件,节点式地牢生成 | Roguelike 地牢 |
| **Dungeon Architect** | Unity/Unreal 地牢生成 | 房间-走廊地牢 |
| **WFC Unity** | Wave Function Collapse 实现 | 2D/3D tile-based |
---
## 经典案例分析
### 《Spelunky》—— 参数化关卡设计
```
设计核心:4x4 网格 + 预设计模板块
每个格子可选模板:
├── 出生点(固定)
├── 出口(固定,底部)
├── 普通房间(20+ 变体)
├── 商店(固定规则出现)
├── 宝藏室(概率出现)
└── 陷阱房(后期关卡概率提升)
关键约束:
- 左边必有通向右边的路径
- 下方必有可到达的通道(防止摔死)
- 每个关卡至少 1 个商店 + 1 个宝藏
- 难度参数随关卡深度递增
```
### 《Hades》—— Rogue-lite 叙事集成
| 设计选择 | 实现方式 | 效果 |
|----------|----------|------|
| **死亡即剧情** | 每次死亡触发新对话 | 消解挫败感 |
| **关系进度保留** | NPC 好感度跨局累加 | meta-progress 叙事 |
| **上下文敏感对话** | 根据上局表现选择台词 | 个性化体验 |
| **有限变体池** | 大量手工内容分批次解锁 | 质量与变化平衡 |
### 《No Man's Sky》—— 全程序宇宙
```
生成层级:
- 星系 → 恒星类型、行星数量
- 行星 → 地形、气候、生物群系
- 生物 → 骨骼结构、行为模式、外观
- 植物 → 形态、颜色、生态作用
- 文明遗迹 → 建筑模板 + 腐蚀状态
教训:
- 1.0 版本:生成内容缺乏差异性("每个星球都一样")
- 后续更新:增加更多手工模板、生物行为多样性、任务引导
```
### 《Elite Dangerous》—— 银河系模拟
```
规模:4000 亿+ 星系,全部可访问
技术:种子值 + 算法 → 星系属性
存储:不存储星系数据,实时生成
数据:仅记录玩家发现和改变的状态
```
---
## 最佳实践清单
- [ ] **从手工设计开始**:先设计 10-20 个手工关卡,提炼模式后再程序生成
- [ ] **约束优于自由**:给生成器更多约束,而非更多自由度
- [ ] **可复现性**:使用确定性种子,便于调试和测试
- [ ] **可视化调试**:提供生成过程可视化工具
- [ ] **玩家反馈闭环**:追踪生成内容的玩家行为数据,持续调优
- [ ] **质量门控**:生成内容必须经过验证才能进入游戏
- [ ] **混合策略**:手工设计核心路径,程序填充支线内容
- [ ] **渐进揭示**:早期关卡更多手工,后期更多程序(玩家已理解规则)
---
## 相关页面
- [核心机制设计](core-mechanics.md) — 机制与 PCG 的结合
- [关卡设计](level-design.md) — 手工关卡设计原则
- [游戏设计原则](game-design-principles.md) — MDA 框架与 PCG
- [玩家心理学](player-psychology.md) — 随机奖励与心流