关于 procedural-generation
面向 Godot 4.3+ 开发者的程序化生成指南,介绍可复现随机性、噪声地形、地牢、洞穴和基于规则的瓦片生成。
主要功能
- 01使用随机种子复现生成结果
- 02FastNoiseLite 噪声地形
- 03BSP 房间与走廊地牢
- 04细胞自动机洞穴生成
- 05WFC 瓦片约束生成
适用场景
- 01生成可通过种子分享的关卡
- 02创建噪声地形或瓦片地图
- 03构建地牢和洞穴布局
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ jame581/ godotprompter --skill procedural-generation安装后在 Claude Code 中输入/procedural-generation确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/bsp-dungeons.mdcellular-automata.mdnoise-generation.mdwave-function-collapse.md详细介绍
Godot 4.3+ 中的程序化生成
所有示例均面向 Godot 4.3+,不使用已弃用的 API。先介绍 GDScript,再介绍 C#。
**相关技能:**TileMapLayer 用法见 2d-essentials,3D 地形网格见 3d-essentials,向量和变换见 math-essentials,区块加载和性能优化见 godot-optimization。
1. 带种子的随机性
始终使用种子进行可复现的生成。这有助于分享种子、回放和确定性测试。
GDScript
# RandomNumberGenerator — per-instance, seedable
var rng := RandomNumberGenerator.new()
func generate_level(level_seed: int) -> void:
rng.seed = level_seed
var width: int = rng.randi_range(20, 40)
var height: int = rng.randi_range(15, 30)
var enemy_count: int = rng.randi_range(3, 8)
var treasure_chance: float = rng.randf_range(0.05, 0.15)
# AVOID: Global randf()/randi() — one shared generator, randomized at startup
# and advanced by every other caller, so a sequence is hard to reproduce
# USE: rng.randf(), rng.randi(), rng.randf_range(), rng.randi_range()
C#
private RandomNumberGenerator _rng = new();
public void GenerateLevel(ulong levelSeed)
{
_rng.Seed = levelSeed;
int width = _rng.RandiRange(20, 40);
int height = _rng.RandiRange(15, 30);
int enemyCount = _rng.RandiRange(3, 8);
float treasureChance = _rng.RandfRange(0.05f, 0.15f);
}
**提示:**从字符串生成种子,创建可分享的关卡代码:
var level_seed: int = "MyLevel".hash()(C#:GD.Hash("MyLevel"))
2. 基于噪声的生成(FastNoiseLite)
FastNoiseLite 可用于高度图、生物群系分布和 2D 地形。关键参数:noise_type(Perlin / Simplex / Cellular / Value)、frequency(值越低,特征越大)、seed。生成地形时,对每个图块坐标采样噪声,并根据阈值选取图块。
请参阅 references/noise-generation.md,了解基础噪声图生成方法、噪声类型参考表,以及 2D 地形与 TileMapLayer 的操作指南。
3. BSP 地牢生成
二叉空间分割会递归地将一个矩形划分成更小的矩形,在每个叶节点中开辟房间,并用走廊连接同级分区。生成的地牢由网格对齐的房间组成(类似 Roguelike 游戏)。
请参阅 references/bsp-dungeons.md,了解 GDScript 和 C# 中完整的递归分割、房间放置和走廊连接算法。
4. 元胞自动机(洞穴生成)
以约 45% 的密度用随机墙壁和地板填充网格,然后迭代 4–5 次规则:“如果一个单元格的 8 个邻居中至少有 5 个是墙壁,该单元格就变成墙壁。”结果会生成自然的洞穴形状,不会出现笔直的走廊。
请参阅 references/cellular-automata.md,了解完整的 GDScript 和 C# 实现及 TileMapLayer 集成方法。
5. 波函数坍缩(WFC)
WFC 是一种约束求解器:给定包含邻接规则的图块集,选取熵最低的单元格,将其坍缩为有效图块,传播约束,然后重复此过程。生成结果符合图块规则,但实现起来并不简单。
请参阅 references/wave-function-collapse.md,了解概念概述和简化版 GDScript 与 C# 实现。
6. 常见问题
| 现象 | 原因 | 解决方法 |
|---|---|---|
| 每次生成的关卡都相同 | 未为 RNG 设置种子 | 在生成前设置 rng.seed |
| 相同种子生成的关卡不同 | 全局 randf() / randi() 会在启动时随机化,并与所有调用它们的其他代码共享 | 使用专用的 RandomNumberGenerator 实例 |
| 噪声看起来像方块 | 频率过高 | 降低 frequency(尝试 0.01–0.05) |
| 洞穴全是墙壁或全是地板 | fill_chance 过高或过低,或迭代次数太少 | 将 fill_chance 设为 0.40–0.50,并迭代 4–6 次 |
| BSP 房间重叠 | 分割位置太靠近边缘 | 在分割计算中确保留出 min_room_size 缓冲空间 |
| WFC 产生矛盾(没有有效图块) | 邻接规则限制过严 | 添加更多允许的邻居,或实现回溯 |
| 生成耗时过长 | 在一帧内处理整张地图 | 使用 await get_tree().process_frame 将处理分散到多帧中,或使用线程 |
7. 实现检查清单
- 所有生成逻辑都使用可设定种子的
RandomNumberGenerator,绝不使用全局randf()/randi() - 种子与存档数据一同保存,以便重现关卡
- 根据游戏的瓦片/世界规模调整
FastNoiseLite的频率和八度数 - 将大型生成任务分散到多个帧中,或放在线程中运行,以避免卡顿
- 生成的 TileMapLayer 内容尽可能使用地形自动拼接(而非硬编码瓦片坐标)
- BSP 地牢在完成前确认所有房间都已连通
- 洞穴生成通过泛洪填充检查关键点之间是否可达
- 验证玩家出生点位于地板瓦片上,而不是墙内