xiaohongshu
xiaohongshu
godot-migrate-tilemap
Migrates legacy TileMap (Godot 4.0-4.2) to new TileMapLayer system (Godot 4.3+). Handles TileMap node conversion, API migration (set_cell to set_cells_terrain_connect), TileSet resource updates, physics layer mapping, navigation layer conversion, and custom data preservation. Essential for upgrad...
Full skill instructions
Migrates legacy TileMap system to Godot 4.3+ TileMapLayer architecture.
Godot 4.3 introduced a new TileMap system with breaking changes:
| Legacy (4.0-4.2) | New (4.3+) |
|---|---|
Single TileMap node | Multiple TileMapLayer nodes |
set_cell() method | set_cells_terrain_connect() |
| Cell-based coordinates | Layer-based organization |
| Single TileSet resource | Enhanced TileSet with layers |
update_bitmask_region() | Terrain system |
| Manual physics setup | Physics layers per tile |
When this skill is invoked, IMMEDIATELY execute:
ls project.godot 2>/dev/null && echo "✓ Godot project detected" || echo "✗ Not a Godot project"
If NOT a Godot project:
echo "=== Detecting TileMap Usage ==="
echo "TileMap nodes in scenes:"
grep -rn "type=\"TileMap\"" --include="*.tscn" . | wc -l
echo "TileMap references in scripts:"
grep -rn "TileMap" --include="*.gd" . | wc -l
echo "set_cell calls:"
grep -rn "set_cell\|get_cell" --include="*.gd" . | wc -l
echo "update_bitmask calls:"
grep -rn "update_bitmask" --include="*.gd" . | wc -l
echo "tile_set property access:"
grep -rn "\.tile_set" --include="*.gd" . | wc -l
Show the user:
=== TileMap V2 Migration Analysis ===
Project: [project name]
Current: Legacy TileMap (Godot 4.0-4.2 style)
TileMap usage detected:
- TileMap nodes: X
- TileMap references: X
- set_cell/get_cell calls: X
- update_bitmask calls: X
- tile_set access: X
Migration includes:
✓ TileMap → TileMapLayer node conversion
✓ set_cell() → set_cells_terrain_connect()
✓ TileSet resource upgrade
✓ Physics layer mapping
✓ Navigation layer conversion
✓ Custom data preservation
✓ Terrain system setup
✓ Git commit per layer
✓ Backup before changes
⚠️ WARNING: Godot 4.3+ required for new TileMapLayer system
Would you like me to:
1. Proceed with migration (recommended)
2. Show detailed breakdown first
3. Migrate specific TileMaps only
4. Cancel
# Find all TileMap nodes in .tscn files
grep -rn "type=\"TileMap\"" --include="*.tscn" . | while read line; do
file=$(echo "$line" | cut -d: -f1)
echo "Found TileMap in: $file"
done > /tmp/tilemap_scenes.txt
# Find all TileMap references in scripts
grep -rn "extends TileMap\|var.*TileMap\|: TileMap" --include="*.gd" . | while read line; do
file=$(echo "$line" | cut -d: -f1)
echo "TileMap usage in: $file"
done > /tmp/tilemap_scripts.txt
For each TileMap node:
# Extract TileMap configuration from .tscn
grep -A20 "type=\"TileMap\"" scene.tscn | grep -E "tile_set|format|cell|layer"
TileMap V2 Migration Plan:
=========================
1. Node Structure Changes (X TileMaps)
- Convert TileMap → TileMapLayer nodes
- Preserve layer order and names
- Update scene hierarchy
2. API Migration (X scripts)
- set_cell() → set_cells_terrain_connect()
- get_cell() → get_cell_alternative_tile()
- update_bitmask() → terrain system
3. TileSet Updates (X resources)
- Upgrade TileSet format
- Map physics layers
- Configure navigation layers
- Preserve custom data
4. Script Updates (X files)
- Update TileMap references
- Fix method calls
- Update signal connections
Total operations: X
Estimated time: Auto
Godot version required: 4.3+
Backup created: YES
Rollback available: YES
Legacy Structure:
[node name="TileMap" type="TileMap"]
tile_set = ExtResource("1_qwerty")
format = 2
layer_0/name = "Ground"
layer_0/tile_data = PackedInt32Array(...)
layer_1/name = "Walls"
layer_1/tile_data = PackedInt32Array(...)
New Structure:
[node name="Ground" type="TileMapLayer" parent="."]
tile_map_data = PackedByteArray(...)
tile_set = ExtResource("1_qwerty")
[node name="Walls" type="TileMapLayer" parent="."]
tile_map_data = PackedByteArray(...)
tile_set = ExtResource("1_qwerty")
Transformation Process:
Parse legacy TileMap
Generate TileMapLayer nodes
Update scene hierarchy
Legacy Format:
layer_0/tile_data = PackedInt32Array(0, 1, 0, 65536, 1, 0, ...)
New Format:
tile_map_data = PackedByteArray(0, 0, 0, 0, 1, 0, 0, 0, ...)
Note: Direct byte conversion requires Godot's internal format knowledge. Alternative approach:
# Migration script approach
# 1. Load scene with legacy TileMap in Godot 4.3
# 2. Run migration tool script
# 3. Save with new TileMapLayer format
Detection:
grep -rn "set_cell\|get_cell\|update_bitmask" --include="*.gd" .
Common Mappings:
| Legacy API | New API |
|---|---|
set_cell(layer, coords, source_id) | set_cells_terrain_connect(coords_array, terrain_set, terrain) |
get_cell(layer, coords) | get_cell_alternative_tile(coords) |
get_cell_source_id(layer, coords) | get_cell_source_id(coords) |
update_bitmask_region(start, end) | Terrain system (set terrain bits) |
clear_layer(layer) | clear() on TileMapLayer |
erase_cell(layer, coords) | erase_cell(coords) |
Example 1: Setting a cell
Before:
# Legacy TileMap API
tilemap.set_cell(0, Vector2i(5, 3), 1)
tilemap.set_cell(0, Vector2i(5, 4), 1)
tilemap.set_cell(0, Vector2i(6, 3), 1)
After:
# New TileMapLayer API - Using terrain for multiple cells
ground_layer.set_cells_terrain_connect(
[Vector2i(5, 3), Vector2i(5, 4), Vector2i(6, 3)],
0, # terrain_set
1 # terrain_id
)
Example 2: Getting cell data
Before:
var source_id = tilemap.get_cell_source_id(0, coords)
var atlas_coords = tilemap.get_cell_atlas_coords(0, coords)
After:
var source_id = ground_layer.get_cell_source_id(coords)
var atlas_coords = ground_layer.get_cell_atlas_coords(coords)
Example 3: Autotile/Bitmask
Before:
tilemap.set_cell(0, coords, 1)
tilemap.update_bitmask_region(Rect2i(0, 0, 20, 20))
After:
# Using terrain system
ground_layer.set_cells_terrain_connect([coords], 0, 1)
# Terrain automatically connects - no update_bitmask needed!
Legacy: Physics setup per tile in TileSet
New: Dedicated physics layers
# New TileSet setup in Godot 4.3
tileset.set_physics_layer_collision_layer(0, 1)
tileset.set_physics_layer_collision_mask(0, 1)
tileset.set_physics_layer_physics_material_override(0, physics_material)
Legacy: Navigation polygons per tile
New: Navigation layers system
# Enable navigation layer
tileset.set_navigation_layer_enabled(0, true)
# Set navigation polygon for specific tile
var source_id = 1
var atlas_coords = Vector2i(0, 0)
tileset.set_navigation_polygon(0, source_id, atlas_coords, navigation_polygon)
New in 4.3: Custom data per tile
# Define custom data layer
tileset.add_custom_data_layer()
tileset.set_custom_data_layer_name(0, "tile_health")
tileset.set_custom_data_layer_type(0, TYPE_INT)
# Set data on specific tile
tileset.set_custom_data(0, source_id, atlas_coords, 100)
# Create backup tag
git tag tilemap-v1-baseline-$(date +%Y%m%d-%H%M%S)
# Commit any current changes
git add .
git commit -m "Baseline: Pre-TileMap V2 migration" || echo "No changes to commit"
For each TileMap:
Backup scene file
cp scene.tscn scene.tscn.backup
Parse TileMap data
Generate TileMapLayer nodes
Update scripts
Commit changes
git add scene.tscn modified_scripts.gd
git commit -m "Migrate: TileMap to TileMapLayer in scene.tscn
- Converted TileMap node to TileMapLayer nodes
- Updated script references
- Migrated set_cell() calls
- Preserved layer data"
# Check scene loads in Godot
godot --headless --quit-after 5 project.godot 2>&1 | tee test.log
# Check for errors
if grep -q "ERROR\|SCRIPT ERROR" test.log; then
echo "⚠️ Migration error detected!"
git reset --hard HEAD~1
echo "✓ Reverted to pre-migration state"
exit 1
fi
rm test.log
# Setup terrain for autotiling
tileset.add_terrain_set()
tileset.set_terrain_set_mode(0, TileSet.TerrainMode.CONNECT)
# Add terrain
tileset.add_terrain(0, 0)
tileset.set_terrain_name(0, 0, "Ground")
# Assign terrain to tiles
# (Configure in Godot editor for best results)
# Configure physics layers per tile type
tileset.set_physics_layer_collision_layer(0, 1) # Layer 1
tileset.set_physics_layer_collision_mask(0, 1) # Detect layer 1
# Enable navigation on specific tiles
navigation_layer.enabled = true
tileset.set_navigation_layer_enabled(0, true)
Before (Godot 4.2):
# level.tscn
[node name="TileMap" type="TileMap"]
tile_set = ExtResource("1_tileset")
format = 2
layer_0/name = "Ground"
layer_0/tile_data = PackedInt32Array(...)
layer_1/name = "Obstacles"
layer_1/tile_data = PackedInt32Array(...)
# level.gd
extends Node2D
@onready var tilemap: TileMap = $TileMap
func _ready():
# Set some cells
tilemap.set_cell(0, Vector2i(10, 5), 1)
tilemap.set_cell(0, Vector2i(11, 5), 1)
tilemap.update_bitmask_region(Rect2i(10, 5, 2, 1))
# Get cell info
var source_id = tilemap.get_cell_source_id(0, Vector2i(10, 5))
print("Cell source: ", source_id)
func generate_level():
for x in range(20):
for y in range(15):
tilemap.set_cell(0, Vector2i(x, y), randi() % 3)
tilemap.update_bitmask_region(Rect2i(0, 0, 20, 15))
After (Godot 4.3):
# level.tscn
[node name="Ground" type="TileMapLayer" parent="."]
tile_set = ExtResource("1_tileset")
tile_map_data = PackedByteArray(...)
[node name="Obstacles" type="TileMapLayer" parent="."]
tile_set = ExtResource("1_tileset")
tile_map_data = PackedByteArray(...)
# level.gd
extends Node2D
@onready var ground_layer: TileMapLayer = $Ground
@onready var obstacles_layer: TileMapLayer = $Obstacles
func _ready():
# Set cells using terrain
ground_layer.set_cells_terrain_connect(
[Vector2i(10, 5), Vector2i(11, 5)],
0, # terrain_set
1 # terrain_id
)
# Get cell info
var source_id = ground_layer.get_cell_source_id(Vector2i(10, 5))
print("Cell source: ", source_id)
func generate_level():
var coords_array = []
for x in range(20):
for y in range(15):
coords_array.append(Vector2i(x, y))
# Use terrain for efficient bulk placement
ground_layer.set_cells_terrain_connect(coords_array, 0, randi() % 3)
Before:
# Access different layers
func set_ground_cell(coords: Vector2i, tile: int):
tilemap.set_cell(0, coords, tile)
func set_wall_cell(coords: Vector2i, tile: int):
tilemap.set_cell(1, coords, tile)
func clear_all():
tilemap.clear_layer(0)
tilemap.clear_layer(1)
After:
# Access different layers
func set_ground_cell(coords: Vector2i, tile: int):
ground_layer.set_cells_terrain_connect([coords], 0, tile)
func set_wall_cell(coords: Vector2i, tile: int):
obstacles_layer.set_cell(coords, tile)
func clear_all():
ground_layer.clear()
obstacles_layer.clear()
Migration complete when:
set_cell(layer, ...) calls remainupdate_bitmask calls remainProblem: Old code used layer indices (0, 1, 2)
Solution: Replace with explicit layer references
# Before
tilemap.set_cell(0, coords, tile) # Layer 0
# After
ground_layer.set_cell(coords, tile) # Named layer
Problem: update_bitmask_region() no longer exists
Solution: Use terrain system or set_cells_terrain_connect()
# Before
for x in range(width):
for y in range(height):
tilemap.set_cell(0, Vector2i(x, y), source_id)
tilemap.update_bitmask_region(Rect2i(0, 0, width, height))
# After
var coords_array = []
for x in range(width):
for y in range(height):
coords_array.append(Vector2i(x, y))
ground_layer.set_cells_terrain_connect(coords_array, 0, source_id)
Problem: Coordinate system differences between TileMap and TileMapLayer
Solution: Both use Vector2i, but ensure local vs global coordinates
# Both work similarly
var local_coords = tilemap.local_to_map(position) # Legacy
var local_coords = layer.local_to_map(position) # New
If migration causes issues:
# Find baseline tag
git tag | grep "tilemap-v1-baseline"
# Reset to pre-migration
git reset --hard <baseline-tag>
# Or restore individual scene from backup
cp scene.tscn.backup scene.tscn
Minimum: Godot 4.3+
Check version:
godot --version
# Should show 4.3 or higher
Upgrade notes:
Use with:
godot-modernize-gdscript - Update syntax before TileMap migrationgodot-refactor - Clean up code after migrationgodot-setup-navigation - Configure navigation on new TileMapLayerBest practice workflow:
This skill handles the complex TileMap API changes in Godot 4.3, preserving your level data while upgrading to the modern TileMapLayer system.
xiaohongshu
technical spec
product ux expert
database patterns
Conduct multi-agent task orchestration and workflow coordination.
Initialize project with Conductor artifacts (product definition,
Expert in web animations, transitions, and motion design using Framer Motion and CSS
Creates Mermaid and ASCII diagrams for flowcharts, architecture, ERDs, state machines, mindmaps, and more. Use when user mentions diagram, flowchart, mermaid, ASCII diagram, text diagram, terminal diagram, visualize, C4, mindmap, architecture diagram, sequence diagram, ERD, or needs visual docume...
PostgreSQL bindings for H3 hexagonal grid system. Use when working with H3 cells in Postgres, including spatial indexing, geometry/geography integration, and raster analysis.
Context-Driven Development skill for projects using Conductor. Use this skill when you detect a `conductor/` directory in the project, when working on tasks defined in a `plan.md` file, or when the user asks about tracks, specs, or plans. Automatically applies TDD workflow, tracks task completion...
Display project status, active tracks, and next actions
Official Stakpak application containerization standard operating procedure, a step-by-step guidline to properly dockerize applications. This is a rule book curated by the Stakpak Team.
Generate, edit, and beat-sync AI video with leading models in one workspace.
The world's fastest calendar for remote work
Transform Your Design with AI Designer by ImgCreator.ai
Revolutionizing Video Production with AI-Powered Creativity
Extend an image past the frame and let AI fill the new aspect ratio.
Discover your celebrity doppelgänger with StarByFace!
ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.
Opus.ai: Revolutionize Your Web Experience