TileMap (2D) — modular 2D levels
TileMapLayer, TileSet, terrains, autotile, navigation for 2D projects in Godot 4.x.
This encyclopedia is about 3D, but Godot has a first-class 2D pipeline, and TileMap is the main tool for modular levels (platformers, top-down RPGs, dungeon crawlers, city builders).
TileMap architecture in Godot 4.x
With Godot 4.3 an important change happened: the classic TileMap node is deprecated in favor of
TileMapLayer nodes.
| TileMap (legacy) | TileMapLayer (current) | |
|---|---|---|
| Year | before 4.3 | since 4.3, recommended |
| Layers | Inside a single node as an array | Each layer is a separate node |
| Performance | Worse on scenes with layer modulation | Better — each layer is processed in parallel |
| Editor UX | Complex UI for multi-layer | Simple: drag-and-drop nodes to reorder |
In a new project, use TileMapLayer. One node = one layer (for example, background → details → objects).
Key concepts
- TileSet — a
Resourcewith a list of all available tiles (sprite + collision + nav data). - TileMapLayer — a
Node2Dthat draws tiles from a TileSet on a coordinate grid. - Tile — a cell of the TileSet: sprite source + collision shape + custom data layers.
- TileSetAtlasSource — a tile source from a single image (atlas-style).
- TileSetScenesCollectionSource — a tile source from PackedScenes (animated / complex).
A CSS sprite sheet with background-position + Pixi.js tilemap libraries.
Creating a TileSet
- In FileSystem → New Resource → TileSet.
- Double-click — the TileSet editor opens (bottom panel).
- Click
+→ New Atlas Source → choose a texture (a sprite atlas with tiles). - The editor automatically slices the atlas into cells (16×16 by default). Each cell is a separate tile.
- For each tile you configure:
- Physics layer — a collision shape (select Physics Layer 0, draw a polygon).
- Navigation layer — for NavigationAgent2D.
- Custom data layers — arbitrary properties (for example, “damage_per_tick” for lava).
TileMapLayer in action
World
├── TileMapLayer_Background
│ tile_set: floor.tres
│ y_sort_enabled: false
├── TileMapLayer_Walls
│ tile_set: floor.tres # the same TileSet
│ y_sort_enabled: false
└── TileMapLayer_Objects
tile_set: objects.tres
y_sort_enabled: true # for top-down with depth
In the Scene View select the layer → TileMap Editor (bottom panel) → choose a tile from the palette → draw.
Programmatic control
extends TileMapLayer
func _ready() -> void:
# Coordinates in TileMap are Vector2i (integers)
set_cell(Vector2i(0, 0), 0, Vector2i(0, 0)) # source_id, atlas_coords
# source_id — the source index in the TileSet
# atlas_coords — the tile position in the atlas
# Erase a tile
erase_cell(Vector2i(0, 0))
# Get tile data
var tile_data := get_cell_tile_data(Vector2i(0, 0))
if tile_data:
var dmg = tile_data.get_custom_data("damage_per_tick")
print(dmg)
# Convert between world ↔ map coordinates
var map_pos := local_to_map(Vector2(64, 32))
var world_pos := map_to_local(Vector2i(2, 1))
Terrains — auto-connecting tiles
The key feature for beautiful levels. You paint a zone (grass, water, road), and the engine itself picks the correct tile for each cell based on its neighbors.
- In the TileSet editor → choose the Terrains tab.
- Add a Terrain Set → a new Terrain (“Grass”).
- On each tile in the Atlas, mark which of its corners belong to the “Grass” terrain.
- In the TileMap editor switch the mode to Terrains → choose Grass → “paint” a large area.
- For each cell Godot automatically picks the tile from the set whose corners match its neighbors.
This is terrain matching by corners and/or sides — the classic “auto-tile”. You can draw a curved grass border across the map, and the seam with the road / water will be perfect.
Godot Terrains uses corner-based matching (the 4 corners of a tile have a bitmask). This enables smooth transitions and diagonal-correct uneven borders. The old Wang-tile scheme (with side-based matching) also exists in the API, but corner is the modern way.
Navigation on a TileMap
If you want a NavigationAgent2D to walk across your map:
- In TileSet → Physics Layers is NOT enough — that’s collision, not nav.
- In TileSet → Navigation Layers → add a layer.
- On each walkable tile → draw a navigation polygon (usually matching the tile’s border).
- On the TileMapLayer node → Navigation Layers → check the one being used.
- Godot automatically builds a navmesh from all walkable tiles.
Animated tiles
In the TileSet Atlas Source → select a tile → in the Inspector → Animation Frames Count > 1. Specify the duration of each frame. Movement / texture animation works without scripts — TileMapLayer updates automatically.
Use cases: flowing water, torches, flickering crystals.
Pitfalls
- Tile size in TileSet vs TileMapLayer — they must match. If you changed it in the TileSet → repaint the layers.
- Physics doesn’t work by default — the Physics Layer must be enabled and the tile must have a collision polygon. Often forgotten.
- Y-sort on a single layer does not play well with tile collision — for top-down with proper sorting of a character behind a tree, use an Object Layer (Y-sort) separate from the ground layers.
- Custom data layers — powerful, but remember the names. A typo
"damage_per_tick"vs"damagePerTick"— silent fail.
When TileMap is NOT the choice
- A 3D scene — these are 2D nodes; in 3D use GridMap (see chapter 21).
- Hex grid — TileMap supports hex layout (Inspector → tile_shape = HALF_OFFSET_*), but the editor is more convenient for orthogonal. For a serious hex project, look at community plugins.
- Voxel-style 3D — that’s a completely different task; TileMap is not suitable.