上次我们用 TileMapLayer 把「画格子」搭出了可玩关卡。但真画起来你会发现一件很不 AI 的事:地形接缝得靠手摆。草地边上要压草、平台拐角要换瓦片、洞穴地面和墙壁的交界不能糊在一起。一关几百格,手摆到第三十格就开始怀疑人生;更别说程序化生成关卡,那段拼接代码写起来比游戏逻辑还长。Godot 的 terrain(地形自动拼接)就是专门解决这件事的——你只画「这块是草地」,剩下的接缝它自己挑图。对用 AI 出素材的独立开发者,这是性价比最高的一次学习投入。
今日速览
- Terrain 不是一个节点、也不是一类特殊瓦片。它只是给 atlas 瓦片加的一层「属性」,再配一个专门的绘制模式。任何地形瓦片照样能当普通瓦片单张画。
- 三种匹配模式决定你要准备多少张图:
Match Corners and Sides(3×3、8 邻域、最全 47 张)、Match Corners(2×2、4 角)、Match Sides(4 边)。素材少就选 Corners。 - Terrain Set 和 Terrain 的 ID 都从 0 开始,
-1表示「没有」。这是新手第一个坑:不先把 Terrain Set 设成 ≥0,Terrain 那一栏根本改不动。 - Peering Bits 的
-1不是「不匹配」,而是「必须是空/别的」。它决定了这张图只在「上边没东西」时才出现。 - 代码里用
set_cells_terrain_connect(),一次传一批格子,Godot 帮你把整片地形的接缝重算完——程序化关卡的关键 API。
核心学习内容
一、Terrain 的本质:属性 + 绘制模式
官方文档说得很直白:terrain 是 Godot 3.x autotile 的「更强大替代品」,但实现方式变了——它不再是瓦片的一种,而是瓦片上的属性集合。你在 TileSet 编辑器里给某张瓦片填上 Terrain Set = 0、Terrain = 0,它就「属于」0 号地形集的 0 号地形。
然后 TileMap 编辑器多出一个 Terrains 标签页,里面三种绘制方式:
- Connect:把新画的格子跟周围所有同层瓦片连起来,最省事;
- Path:只跟「同一笔画」内的格子连,松手就断开——适合让两条路并排走却互不粘连;
- Tile-specific:直接从地形里挑一张具体瓦片,用来处理自动规则搞不定的冲突。
这个设计对 AI 素材特别友好:AI 出的 tilesheet 常常缺几张、多几张、边缘不齐,你完全可以只给一部分瓦片打上地形属性,缺的用 Tile-specific 手动补,不必强求 47 张齐全。
二、三种模式,对应三张不同的素材清单
这是今天最该记住的一张表:
| 模式 | 看哪些邻居 | 位数 | 完整集合 | 适用 |
|---|---|---|---|---|
| Match Corners and Sides | 上下左右 + 4 个斜角 | 8 bit | 47 张 | 平台、洞穴、有内拐角的块状地形 |
| Match Corners | 只有 4 个斜角 | 4 bit | 16 张 | 极简像素风、不关心直边的 |
| Match Sides | 只有上下左右 | 4 bit | 16 张 | 顶部平台、单线管道 |
47 张听着吓人,但实际做 2D 平台游戏,多数人只需要「顶边 + 左/右边 + 4 个外角 + 4 个内角 + 中心」十几张,剩下的用 Tile-specific 覆盖。这也是让 AI 出图的正确姿势:别让它一次画 47 张,让它按「角色」画——中心块 1 张、左右边各 1 张、顶边 1 张、四个外角 4 张、四个内角 4 张,共 12 张就够开局。
三、Peering Bits:-1 才是精髓
官方举的例子很关键:一张瓦片如果所有 bit 都 ≥0,它只有在周围 8 格全是同 terrain 时才出现(= 完全被包住的中心块)。如果它的 左上、上、右上三个 bit 设为 -1,那它只在「上面是空的」时出现(= 地表那一排)。
所以 Peering Bits 不是在描述「我旁边有什么」,而是在声明「我要求旁边是什么」:-1 = 必须是空或别的地形,0 = 必须是 0 号地形,1 = 必须是 1 号地形。这张表就是自动拼接的全部逻辑,填对了,一画就是成品;填错了,就会出现「草地悬空还长着内角」这种诡异画面。
手工填 47 行 × 8 列是纯体力活,这正是 DeepSeek 该上场的地方:让它按「上/右上/右/右下/下/左下/左/左上」的固定顺序,帮你把每种瓦片该填的 8 位值算出来,输出成表格你照着敲。
四、程序化生成:一条 API 顶一百行
关卡是随机生成的时候,靠编辑器手画不现实。Godot 给了两个函数:
# 一次把一批格子按地形规则连好(Connect 模式)
tilemap.set_cells_terrain_connect(cells, terrain_set, terrain, ignore_empty_terrains)
# 按「一条路径」连(Path 模式),顺序敏感
tilemap.set_cells_terrain_path(path, terrain_set, terrain, ignore_empty_terrains)
典型流程是:用 FastNoiseLite 生成一张「这块是不是实心」的布尔网格 → 把实心格收进 cells 数组 → 一次性调用 set_cells_terrain_connect()。
三个必踩的坑:
- 必须在 TileSet 里真的有对应 terrain,否则调用静默无效(不报错,最坑)。
- 别在循环里逐格调用。
set_cells_terrain_connect()每次都会重算整片连接,逐格调用是 O(n²) 的打字机,正确做法是攒够一批再传。文档也提醒changed信号会因此高频触发。 - 程序化生成的地形记得同步给碰撞与导航:TileSet 里给地形瓦片配好物理层/导航多边形,否则玩家会直接掉进你刚画好的洞里。
🎯 DeepSeek 提示词
提示词 1:让它帮你算 Peering Bits 表(治「47 张填到眼花」)
你是 Godot 4 的 TileSet 专家。我要给一个 2D 平台游戏做地形自动拼接(terrain autotiling),
使用 Match Corners and Sides 模式(8 邻域)。
【我的瓦片清单】
中心块、上边、下边、左边、右边、左上外角、右上外角、左下外角、右下外角、
左上内角、右上内角、左下内角、右下内角(共 13 种)
【任务】
1. 对每一种瓦片,给出它在 8 个 Peering Bits 上应填的值。
2. 位顺序固定为:上、右上、右、右下、下、左下、左、左上。
3. 取值只能是 -1(该方向必须为空/不同地形)或 0(该方向必须是同地形)。
4. 输出一个 Markdown 表格:瓦片名 | 8 位值(按上述顺序)| 一句话解释这张图为什么在这个位置出现。
5. 表格后附 3 条「常见填错症状 → 修正哪一位」的排查清单。
【约束】
- 不要解释 Godot 版本历史,不要给代码,只给表。
- 如果某个瓦片在 Match Corners and Sides 下无法用单一规则表达,直接指出并说明该用 Tile-specific 覆盖。
用法:拿到表照着在 TileSet 编辑器里填,13 行比 47 行省一半时间以上。
提示词 2:让它写程序化地形生成脚本(噪声 → terrain connect)
你是 Godot 4 GDScript 工程师,请写一个程序化地形生成脚本。
【目标】
在 TileMapLayer 上用 FastNoiseLite 生成一条可玩的 2D 平台关卡,并用地形自动拼接把接缝处理好。
【环境】
- Godot 4.4,TileMapLayer 节点名 TerrainLayer
- TileSet 已有 1 个 terrain set(id=0),1 个 terrain(id=0)
- 瓦片大小 16×16,重力向下,角色能站住即可
【要求】
1. 用 FastNoiseLite 生成地表高度曲线:宽度 world_width 格,保证顶部 6 格是空的。
2. 把地表以下 N 格填成实心,收集进 Array[Vector2i]。
3. 只调用一次 set_cells_terrain_connect(cells, 0, 0, true),不要逐格调用。
4. 生成完成后,把出生点放在地表上方,并在控制台打印生成耗时(毫秒)。
5. 全部参数用 @export 暴露:world_width、fill_depth、noise_seed、noise_frequency。
6. 关键行加中文注释,说明「为什么这样写」。
【输出格式】
- 一个完整的 .gd 文件内容,可直接保存使用。
- 代码后附 3 行「如何在场景里挂载并运行」的说明。
- 最后列出 2 个最容易出错的点(例如 terrain id 不匹配、cells 为空)。
用法:直接存成
terrain_generator.gd,挂到 TileMapLayer 上,改noise_seed就能刷关。
提示词 3:接缝错乱的 debug 提示词
你是 Godot 4 TileMap 的 debug 专家。我的地形自动拼接出问题了,请帮我定位。
【症状】(按实际情况删改)
- 草地右边缘出现了内角瓦片
- 两块地形之间有一格宽的缝隙,露出背景
- 某些格子完全不显示瓦片,但 TileMap 里能看到占位方块
【我的配置】
- 模式:Match Corners and Sides
- 瓦片数:13 张,terrain set id=0,terrain id=0
- 绘制方式:Connect
- 素材来源:AI 生成的 tilesheet,统一 16×16,有透明边距
【请按顺序回答】
1. 列出 5 个最可能的原因,按概率从高到低排序。
2. 每个原因给出「在编辑器里点哪里、看什么」的验证步骤(具体到面板名)。
3. 给出对应的修法,优先给不需要重画素材的方案。
4. 如果问题出在 tilesheet 本身(尺寸/边距/UV 溢出),告诉我怎么在 TileSet 的 atlas 属性里补救。
【约束】
- 不要泛泛说「检查配置」,每条都要可操作。
- 如果我描述的信息不足以判断,先列出你需要我补充的 2 条信息。
用法:出问题时把症状段改成你自己的现象,其余别动。它给的验证步骤基本能覆盖 80% 的接缝 bug。
学习心得
今天我们其实只学了一个概念:把「摆图」变成「声明意图」。以前是「这一格放哪张图」,现在是「这一格是草地」——前者是体力活,后者是设计。这件事对「用 DeepSeek 做一款 Steam 游戏」的意义比看起来大:
第一,它把美术工作量从 O(关卡格数) 压到 O(瓦片种类)。AI 出 13 张风格统一的瓦片,比出 200 张拼接图现实得多,而 13 张足够撑起一整款平台游戏的地表。
第二,它让程序化关卡真正可行。Roguelike、无限跑酷、随机地牢这些「一局一个新关卡」的品类,靠手摆是不可能上 Steam 的;有了 terrain connect,一段几十行的生成脚本 + DeepSeek 调参就能出可玩的关。
第三,它是能被写进提示词的知识。Peering Bits 是一张确定的表,不是审美判断——这种「有唯一正确答案」的活,正是 DeepSeek 最擅长、也最该被外包的部分。你要练的不是背 47 个 bit,而是把这类表格化问题识别出来、打包成提示词。
明日关注
- 把 13 张瓦片清单真的画出来(或用 AI 出一版),在 TileSet 里跑通一次 Connect 绘制,确认没有接缝
- 试一次
set_cells_terrain_path():让两条并排的路不粘连,理解 Connect 与 Path 的差别 - 给地形瓦片补上物理层与导航多边形,让程序化生成的关卡「能站、能追」
本文由自动化学习流水线每日生成,坚持即学即记。
评论