簡介
Godot 4 徹底重寫了 TileMap 系統。如果你曾在 Godot 3 中使用 TileMap,幾乎所有東西都變了 — TileSet 編輯器、圖塊的定義方式、自動拼貼、圖層以及 GDScript API。本指南將從零開始講解全新的架構。
Godot 3 使用者:舊有的 autotile、set_cellv() 與 cell_size 全部已被移除。請參閱頁面底部的從 Godot 3 遷移章節。
全新的 TileMap 架構
Godot 4 的 TileMap 系統由兩個主要元件組成:
- TileMap 節點 — 你加入場景的節點。它持有一個或多個圖層,並參照一個 TileSet 資源。
- TileSet 資源 — 定義圖塊本身。包含來源(圖集、場景集合等)、物理圖層、導航圖層、自訂資料圖層以及地形集。
關鍵變更:在 Godot 3 中,圖塊大小是在 TileMap 節點上設定的。在 Godot 4 中,圖塊大小改為在 TileSet 資源中定義,而 TileMap 只是參照它。
TileSet 來源
一個 TileSet 可以擁有多個來源,每個來源都以一個 source_id(整數)來識別。來源類型包括:
- TileSetAtlasSource — 最常見的類型。一張包含多個以網格排列圖塊的紋理圖片。
- TileSetScenesCollectionSource — 每個圖塊都是一個打包場景,適合用於動畫或可互動的圖塊。
設定 TileSet
步驟 1:建立 TileSet 資源
- 在場景中加入一個 TileMap 節點。
- 在檢視器中點擊 Tile Set 屬性並選擇 New TileSet。
- 設定 Tile Size(例如 16x16 或 32x32)。
步驟 2:新增圖集來源
- 點擊 TileSet 以開啟底部面板的 TileSet 編輯器。
- 點擊 + 按鈕並選擇 Atlas。
- 將你的圖塊集圖片拖曳到 Texture 屬性中。
- 編輯器會根據你的圖塊大小自動將其分割成圖塊。你可以調整紋理區域與邊界。
步驟 3:設定圖塊屬性
在 TileSet 編輯器中,你可以加入各種套用到所有圖塊的圖層類型:
- Physics Layers — 圖塊的碰撞形狀
- Navigation Layers — 供尋路使用的可行走多邊形
- Custom Data Layers — 任意的具型別資料(bool、int、float、String 等)
- Terrain Sets — 用於自動拼貼(Godot 3 autotile 的替代方案)
TileMap 圖層
單一 TileMap 節點就能包含多個圖層。相較於 Godot 3 需要為背景與前景使用各自獨立的 TileMap 節點,這是一大改進。每個圖層都可以擁有自己的 z-index、y-sort 與 modulate 設定。
常見的圖層配置:
- Layer 0 — 背景(地面、地板) — z-index: -1
- Layer 1 — 地形(牆壁、障礙物) — z-index: 0
- Layer 2 — 前景(顯示在玩家上方的裝飾) — z-index: 1
圖層的 GDScript API
# Set a cell on layer 0
tilemap.set_cell(0, Vector2i(5, 3), source_id, atlas_coords)
# Get cell info
var source = tilemap.get_cell_source_id(0, Vector2i(5, 3))
var coords = tilemap.get_cell_atlas_coords(0, Vector2i(5, 3))
# Erase a cell
tilemap.erase_cell(0, Vector2i(5, 3))
# Check if a cell is occupied
if tilemap.get_cell_source_id(0, Vector2i(5, 3)) != -1:
print("Cell has a tile")
API 提示:set_cell() 的第一個參數永遠是圖層索引(0、1、2...)。第二個是以 Vector2i 表示的儲存格位置。第三個是 source_id,第四個是以 Vector2i 表示的 atlas_coords。
地形系統(自動拼貼)
地形系統取代了 Godot 3 的 autotile。它會根據相鄰的圖塊自動選取正確的圖塊變體。
設定地形
- 在 TileSet 中加入一個 Terrain Set(檢視器 → Terrain Sets → Add Element)。
- 選擇地形模式:Match Corners and Sides(47 個圖塊)、Match Corners(16 個圖塊)或 Match Sides(16 個圖塊)。
- 在該集合內加入地形類型(例如「Grass」、「Dirt」、「Water」)。
- 在 TileSet 編輯器中切換至 Select 模式,選取一個圖塊,然後在每個圖塊上繪製地形對接位元(peering bits)。
繪製地形
地形設定完成後,切換至 TileMap 編輯器並選擇 Terrains 分頁。選擇你的地形類型並直接在地圖上繪製,Godot 會自動選取正確的圖塊變體。
# Set terrain programmatically
tilemap.set_cells_terrain_connect(0, [Vector2i(5, 3)], 0, 0)
# Parameters: layer, cells array, terrain_set, terrain index
圖塊上的物理
若要為圖塊加入碰撞:
- 在 TileSet 檢視器中加入一個 Physics Layer。
- 設定此物理圖層所使用的碰撞圖層(collision layer)與遮罩(mask)。
- 在 TileSet 編輯器中切換至 Physics 分頁,並在每個圖塊上繪製碰撞多邊形。
提示:你可以為不同的圖塊類型設置多個物理圖層。例如,一個圖層用於牆壁(阻擋移動),另一個用於危險物(透過 Area2D 重疊觸發傷害)。
圖塊上的自訂資料
自訂資料圖層讓你能為任何圖塊附加具型別的中繼資料。這對遊戲邏輯極為實用。
設定自訂資料
- 在 TileSet 檢視器中加入一個 Custom Data Layer。
-
為其命名(例如「is_destructible」)並設定型別(例如
bool)。 - 在 TileSet 編輯器中切換至 Custom Data 分頁,並逐一為每個圖塊設定值。
在程式碼中讀取自訂資料
var tile_data = tilemap.get_cell_tile_data(0, Vector2i(5, 3))
if tile_data:
var is_destructible = tile_data.get_custom_data("is_destructible")
var damage = tile_data.get_custom_data("damage")
if is_destructible:
destroy_tile(Vector2i(5, 3))
常見的自訂資料範例:
is_destructible: booldamage: intmovement_cost: floattile_type: String(例如 "water"、"lava"、"ice")spawn_chance: float
程序化圖塊擺放
使用全新的 API 以程式方式擺放圖塊相當簡單:
# Fill a rectangular area
for x in range(20):
for y in range(10):
tilemap.set_cell(0, Vector2i(x, y), 0, Vector2i(0, 0))
# Random tile placement
for x in range(50):
for y in range(50):
if randf() > 0.7:
tilemap.set_cell(0, Vector2i(x, y), 0, Vector2i(1, 0))
else:
tilemap.set_cell(0, Vector2i(x, y), 0, Vector2i(0, 0))
# Get all used cells on a layer
var used_cells: Array[Vector2i] = tilemap.get_used_cells(0)
print("Layer 0 has ", used_cells.size(), " tiles")
# Clear all tiles on a layer
tilemap.clear_layer(0)
# Clear everything
tilemap.clear()
世界座標與地圖座標的轉換
# Convert world position to map coordinates
var map_pos: Vector2i = tilemap.local_to_map(world_position)
# Convert map coordinates to world position (center of tile)
var world_pos: Vector2 = tilemap.map_to_local(Vector2i(5, 3))
# Example: check what tile the player is standing on
var player_tile = tilemap.local_to_map(tilemap.to_local(player.global_position))
var tile_data = tilemap.get_cell_tile_data(0, player_tile)
if tile_data:
var tile_type = tile_data.get_custom_data("tile_type")
print("Player is on: ", tile_type)
從 Godot 3 遷移
| Godot 3 | Godot 4 |
|---|---|
TileMap.cell_size |
TileSet.tile_size |
set_cellv(pos, tile_id) |
set_cell(layer, pos, source_id, atlas_coords) |
get_cellv(pos) |
get_cell_source_id(layer, pos) |
autotile |
地形系統(Terrain Sets) |
| 每個 TileMap 節點一個圖層 | 單一 TileMap 中的多個圖層 |
TileMap.tile_set = preload(...) |
在檢視器中或透過程式碼指派 TileSet 資源 |
world_to_map() |
local_to_map() |
map_to_world() |
map_to_local() |
常見錯誤
-
忘記先建立 TileSet。在你指派 TileSet 資源之前,TileMap 節點不會顯示圖塊編輯器。請在檢視器中建立一個。
-
錯誤的 source_id。如果你只有一個圖集來源,它的
source_id就是0。加入第二個來源會使其成為source_id = 1。請查看 TileSet 編輯器的底部面板 — 每個來源分頁都會顯示其 ID。 -
把 atlas_coords 與圖塊 ID 混淆。在 Godot 4 中,並沒有簡單的圖塊 ID。取而代之的是,你透過圖塊在圖集網格中的位置,以
Vector2i(column, row)來參照它們。 -
未指定圖層參數。每個儲存格操作都需要以圖層索引作為第一個引數。忘記它會導致引數錯誤。
-
使用
set_cellv()。此方法已不再存在。請使用具有新簽章的set_cell()。