Godot Tilemap in 2026: TileMapLayer Migration Guide
The Godot TileMap node is deprecated. As of Godot 4.3, released August 15, 2024 , the supported way to build a tile-based 2D world is one TileMapLayer node per layer, sharing a single TileSet resource. The official class reference tells you to convert via the toolbox icon in the bottom panel, but the actual migration has sharp edges that the docs do not mention.
TileMap is deprecated, not removed. Existing scenes still load and play. New projects should start with TileMapLayer because every Godot 4 tilemap tutorial after mid-2024 assumes it.
The editor’s one-click converter only works on scenes you can open directly. Tilemaps stored inside
.tresresources or instanced scenes require a manual workaround that’s caught more than one developer for a day.Godot 4’s terrain matching is less reliable than Godot 3’s autotiles. If your game procedurally paints terrain at runtime (a Dome Keeper, a farming sim, a base-builder), read the terrain section before committing.
One node per layer, not one node with hidden layers
The old TileMap held layers internally. You added them in the inspector, then clicked a tab at the bottom of the editor to switch which layer your brush painted. The Godot 4.3 release notes state plainly: the old design “was not in line with Godot Engine’s design philosophy in general.”
TileMapLayer is exactly what the name says. Each layer is a scene node. Order is set by position in the tree. Layers share a TileSet resource via a property on each node. You select a layer by clicking its node, not a tab.
The practical upshot:
| Capability | TileMap (deprecated) | TileMapLayer |
|---|---|---|
| Layer count | Stored as array | One per node |
| Per-layer collision toggle | No | collision_enabled |
| Per-layer navigation toggle | No | navigation_enabled |
| Per-layer occlusion | No | occlusion_enabled |
| Per-layer z-index ordering | Manual | Node tree order |
| Y-sort origin | Per layer (hidden) | y_sort_origin property |
| Per-layer custom shader | Awkward | Standard CanvasItem material |
| Coordinate range | 16-bit signed | 16-bit signed (unchanged) |
The 16-bit coordinate limit, documented on the class page , is unchanged: X and Y clamp between -32768 and 32767. Larger worlds chunk across multiple TileMapLayer nodes anyway, so the limit rarely bites.
The one-click path
Select the TileMap node. Open the bottom TileMap panel. Click the toolbox icon in the top-right. Choose Extract TileMap layers as individual TileMapLayer nodes. The TileMap becomes a parent Node2D with one TileMapLayer child per former layer, each carrying its own tile_map_data PackedByteArray.
The case the editor cannot fix
Reddit user greenflySAU described the painful version migrating their game tankies to 4.3. Their scenarios stored tile data as PackedInt32Array blobs inside .tres files; the editor converter only operates on visible scenes. For each resource they had to revert the parent scene, copy the array into the scene as a text edit, open in Godot, run the converter, then copy the resulting PackedByteArray back into the resource. Per scenario, no scriptable workaround. Lesson: store tile data outside scene files and plan the migration before ship week.
The wire format
The new format is a base64 PackedByteArray packing source ID, atlas coordinates, alternative tile, and physics layer into 12 bytes per cell. It is opaque by design. Never hand-edit it. Use set_cell(), get_cell_source_id(), get_cell_atlas_coords(), and clear() for everything.
Quadrants are the performance knob you’ll forget about
TileMapLayer batches rendering and physics into quadrants. The default size is 16, so a 16×16 square is one canvas item and one physics body group. You only touch it when:
- Setting
physics_quadrant_size = 1for precise cell coords fromget_coords_for_body_rid(). Required when AI agents need to know which tile they hit. - Raising
rendering_quadrant_sizeto 32 or 64 for large outdoor maps; fewer, larger canvas items mean fewer draw calls. - Dropping it to 4 if you toggle layer visibility on small regions often.
The docs note that bumping physics_quadrant_size reduces get_coords_for_body_rid() precision. Real tradeoff.
Godot 3’s autotiles were more reliable
If you paint terrain in the editor and ship the result, Godot 4 is fine. If you paint terrain procedurally at runtime (building roads, tilling soil, destroying walls), read godot-proposals#7670 first.
The proposal author, dandeliondino, points out that Godot 4’s terrain algorithm “isn’t built to handle the complexity of the underlying system” and has high failure rates picking tiles from peering bits. They note that Dome Keeper , shipped on Godot 3, “would not currently be possible using Godot 4 terrains.”
That statement still holds in 2026 with caveats. The community plugin Better Terrain closes the gap for most cases with a 3×3 minimal-style algorithm matching Godot 3’s reliability. It is the first thing to install if your game does anything procedural with terrains.
Pick by map size, not by tutorial popularity
Four ways to build a tile-based world in Godot 4
Pick by map scale, not by tutorial popularity
| Approach | Best for | Learning curve | Scale |
|---|---|---|---|
| TileMapLayer (built-in) | Most 2D games, multi-layer scenes | Medium — terrains require peering-bits thinking | Good up to ~200×200 single layer |
| Better Terrain (plugin) | Complex autotiling, 3x3 minimal style | Low — paints like Godot 3 autotiles | Same as built-in; pure editor sugar |
| Chunked TileMapLayers | Large open worlds, infinite maps | High — write your own load/unload | Scales beyond editor's comfort zone |
| Custom drawing (MultiMesh) | Millions of tiles, no per-cell physics | High — manual culling and collision | Fastest; you control everything |
For most 2D games (platformers, top-down RPGs, procedural roguelikes, small open-world projects), the built-in node is enough. Halls of Torment, a survivors-like shipped on Godot, uses standard TileMapLayer with hand-painted art. Survivors-like maps are not the bottleneck; spawn logic is.
For a town-builder or farming sim where the player edits terrain, install Better Terrain.
For a continuous world larger than ~500×500 tiles, write a chunk loader. The Jackie Codes GodotFest 2025 talk on tilemaps covers serialization and the underused Scene Tiles feature in 50 minutes.
Five pitfalls that eat a day each
Cause and fix for the issues that drive every “godot tilemap not working” forum thread
| Symptom | Cause | Fix |
|---|---|---|
| Collision disappears after migration | Physics layer bitmask reset to defaults when extracting layers | Re-set physics layers on the TileSet resource after running 'Extract' |
| set_cell() changes don't update physics | Collision shapes only rebuild on the next physics tick after a notify | Call tile_layer.notify_runtime_tile_data_update() once per batch |
| Terrains paint the wrong corners | Peering bits set on the wrong terrain or missing tile variants | Open the Terrains tab, paint peering bits for every neighbor combination you have art for |
| Editor freezes on a large map | Single TileMapLayer past ~500×500 cells, brush previews recompute every frame | Split into chunked layers, or reduce viewport zoom while painting |
| Physics body collides with tile seams | Per-tile collision polygons leave a hairline gap between adjacent cells | Use one-way collision OR snap player velocity to integer pixels |
The first two hit hardest on day one of a migration. After running the converter, open the TileSet inspector and verify that physics, navigation, and occlusion layers are still set on each TileData entry. The “Extract” command preserves cell data but not always the per-layer enable flags on the TileSet itself.
Runtime is fast. The editor is the wall.
Editor brush stroke latency vs single TileMapLayer size
Approximate. 60 fps editing budget = ~16 ms. Past 500×500 the brush starts to drag.
Runtime FPS holds up much better than editor latency. The editor lag is the practical limit, not the renderer.
These numbers vary by machine and TileSet complexity, but the curve is real: the editor’s brush preview recomputes every frame while you paint, and past ~500×500 cells per layer it exceeds the 60 fps budget. The renderer itself is much happier; you can ship a 2000×2000 layer that runs at 144 fps, you just cannot edit it comfortably.
The fix is structural. Chunk the world. Eight 250×250 layers feel snappy in the editor and batch the same at runtime.
Generating cells, not painting them
Once your map is a TileMapLayer, every cell is reachable from GDScript through set_cell(coords, source_id, atlas_coords). That makes runtime generation a natural fit for code: noise, wave function collapse, prefab stitching. It also makes it a good target for in-editor AI.
Ziva can read your TileSet, scan your scenes, and write the set_cell loops for procedural maps directly into _ready(). The tutorial on AI-assisted Godot workflows covers the same pattern for other 2D nodes. Tile data is just integers in a PackedByteArray; anything that reads your scene tree can populate it.
For the art that feeds the TileSet, see our pixel art guide.
Two cases warrant a different tool:
- External level editor. Tiled is the de facto 2D level editor across engines. The Tiled-to-Godot importer plugin targets TileMapLayer as of 2025. Useful when your level designer is not a programmer.
- Millions of tiles with no per-cell physics. A
MultiMeshInstance2Ddraws thousands of identical sprites in one draw call. For a galaxy of stars or a particle-field overlay with no collision, MultiMesh beats any tilemap.
Neither replaces TileMapLayer for the 95% case. They are the corners.
For a new Godot 4 project in 2026, start with TileMapLayer. One node per visual layer, one TileSet shared between them, quadrant size left alone unless the renderer or get_coords_for_body_rid() precision says otherwise. If you paint terrain at runtime, install Better Terrain. If you came from Godot 3, the GDScript vs C# comparison and the 2D engine landscape cover what else changed.
The deprecated TileMap will not break tomorrow. But every tutorial written in the last 18 months assumes the new node, and so does every plugin worth installing. Migrate on a quiet afternoon, not the week you ship.