Overview
Tilemaps are essential for creating 2D game backgrounds. However, manually placing each tile at boundaries between grass and dirt or cliff corners is extremely tedious work. Godot 4 includes the "Terrains" feature (equivalent to Autotile in Godot 3), which automatically places appropriate tiles for you.
The Core of Terrains: Understanding Peering Bits
The heart of the Terrains feature is the connection rule definition called Peering Bits. This information tells the engine "what adjacent tiles each tile should have."
Step 1: Creating Terrain Set and Terrains
First, define the terrain types. Here we'll use two terrains as examples: "Grass" and "Dirt."
- Select the
TileMapnode, click theTileSetproperty in the inspector to open theTileSeteditor at the bottom of the screen. - Press the "+" button in the left panel of the
TileSeteditor, select "Terrains" to create a newTerrain Set. - Set the created
Terrain Set'sModeaccording to your tileset structure.Match Corners and Sidesis the most flexible mode considering both corners and edges, suitable for complex terrain boundaries.Match Sidesis a simpler mode considering only edges, suited for tilesets that don't need corner connection patterns. - Expand the
Terrain Setand click "Add array size" twice in theTerrainsproperty to create two Terrain slots. - Set
Nameto "Grass" and "Dirt" respectively, and assign distinctiveColorvalues for identification.
Step 2: Setting Terrain Information on Each Tile (Peering Bits)
This is the most important task. For each tile in the tileset, you'll teach it "which parts belong to which terrain and how they connect."
- Confirm you're in "Select" mode at the top of the
TileSeteditor. - Select the tile you want to configure (e.g., grass center tile) from the tileset image.
- In the inspector on the right, set
Properties>Terrains>Terrain Setto0(the one you created). - In the
Terrainproperty, select which terrain this tile belongs to (e.g., Grass). - Switch to the
Paintbrush (brush icon) and paint connection rules using theTerrain Peeringproperty.
Peering Bits are represented in a 3x3 grid.
- Center square: Represents this tile's own terrain.
- Surrounding 8 squares: Represent the terrain of adjacent tiles in 8 directions.
Step 3: Painting the Map with Terrain Brush
Once all settings are complete, paint the map.
- Select the
TileMapnode in your main scene. - Select the
Terrainstab from the toolbar at the top of the editor. - The palette should show "Grass" and "Dirt" that you configured.
- Select the terrain you want to draw and drag on the map. Godot will automatically place the correct boundary tiles according to Peering Bits rules.
Common Mistakes and Best Practices
| Common Mistake | Best Practice |
|---|---|
| Incomplete Peering Bits configuration | Cover all boundary patterns. It's especially important not to forget setting boundaries between "terrain vs. empty space." |
| Huge single tileset image | Split tilesets by function. Separating by role like "ground," "decoration," "collision" makes management easier. |
| Trying to make everything auto-tile | Combine auto-tile and manual placement. Use Terrains for basic terrain, and manually place special tiles for efficiency. |
Performance Optimization
While it's tempting to create vast maps with the Terrains feature, drawing tens of thousands of tiles can cause performance issues.
- Leverage Layers:
TileMapcan have multiple layers. Split layers based on update frequency and role: ground, buildings, decorations, etc. - Disable Offscreen Drawing: Adding a
VisibilityEnabler2Dnode as a child of theTileMapnode stops processing when it goes off-screen. - Chunking: For extremely vast maps like open worlds, dynamically loading and unloading only the area around the player is effective.
GDScript Integration
Combined with GDScript, the Terrains feature enables procedural dungeon generation and more.
@onready var tile_map: TileMap = $TileMap
func _ready():
# Get tile info at layer 0, coordinates (10, 5)
var cell_coords = Vector2i(10, 5)
var source_id = tile_map.get_cell_source_id(0, cell_coords)
var atlas_coords = tile_map.get_cell_atlas_coords(0, cell_coords)
print("Tile info: Source=%s, Atlas=%s" % [source_id, atlas_coords])
# Place a new tile at layer 0, coordinates (10, 5)
tile_map.set_cell(0, cell_coords, 1, Vector2i(2, 3), 0)
# You can also place tiles using Terrains
func place_tile_with_terrain(layer: int, coords: Vector2i, terrain_set: int, terrain_id: int):
# This function automatically selects and places the correct tile considering surrounding tiles
tile_map.set_cells_terrain_connect(layer, [coords], terrain_set, terrain_id)
Using set_cells_terrain_connect(), you can invoke Terrains' automatic connection functionality from GDScript.
Summary
Setting up the Terrains feature takes some initial effort. However, once configured, your level design efficiency improves dramatically.
- Understanding Peering Bits is the key to mastering Terrains
- GDScript's
set_cells_terrain_connect()enables procedural generation - For large-scale maps, optimize performance with layer splitting and chunk systems
Start by trying the Terrains feature with two simple terrain types to experience its convenience.