소개
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 리소스 — 타일 자체를 정의합니다. 소스(아틀라스, 씬 컬렉션 등), 물리 레이어, 내비게이션 레이어, 커스텀 데이터 레이어, terrain 세트를 포함합니다.
핵심 변경 사항: 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 노드가 여러 레이어를 담을 수 있습니다. 배경과 전경에 각각 별도의 TileMap 노드가 필요했던 Godot 3에 비해 큰 개선점입니다. 각 레이어는 고유한 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입니다.
Terrain 시스템(오토 타일링)
terrain 시스템은 Godot 3의 autotile을 대체합니다. 인접한 타일을 기준으로 올바른 타일 변형을 자동으로 선택합니다.
Terrain 설정하기
- TileSet에서 Terrain Set을 추가합니다(인스펙터 → Terrain Sets → Add Element).
- terrain 모드를 선택합니다: Match Corners and Sides(47타일), Match Corners(16타일), 또는 Match Sides(16타일).
- 세트 안에 terrain 타입을 추가합니다(예: "Grass", "Dirt", "Water").
- TileSet 에디터에서 Select 모드로 전환하고, 타일을 선택한 뒤 각 타일에 terrain peering 비트를 페인트합니다.
Terrain 페인트하기
terrain 설정이 끝나면 TileMap 에디터로 전환하여 Terrains 탭을 선택합니다. terrain 타입을 선택하고 맵에 직접 페인트하면, 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를 추가합니다.
- 이 물리 레이어가 사용할 충돌 레이어와 마스크를 설정합니다.
- 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 시스템 (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()을 사용하세요.