Community코딩 & 개발github.com

ziva-sh/godot-tilemaplayer

Godot 4.3+ TileMapLayer 셀 코드 작성 - set_cell(coords, source_id, atlas_coords), 셀 및 사용자 데이터 읽기, 지우기, 좌표 변환, 지형, TileSet 물리 레이어를 통한 타일 충돌, 바디가 충돌한 타일 찾기, 그리고 deprecated된 TileMap 노드 및 레이어 인덱스 API에서 마이그레이션. GDScript에서 타일 배치, 읽기, 지우기, 코드로 TileSet 구축, 절차적 레벨 생성, 타일 충돌 처리, 또는 Godot 3/4.0 TileMap 코드 이식 시 사용.

godot-tilemaplayer란 무엇인가요?

이 스킬은 Godot 4.3+의 새로운 `TileMapLayer` 노드를 올바르게 사용하는 방법을 설명합니다. `TileMap`은 더 이상 사용되지 않으므로, 각 레이어는 독립적인 `TileMapLayer` 노드로 구성되며, 단일 `TileSet`을 공유합니다. 주요 기능으로는 `set_cell(coords, source_id, atlas_coords)`를 사용한 타일 배치, `get_cell_source_id()`, `get_cell_atlas_coords()`를 통한 셀 읽기, `erase_cell()`을 사용한 지우기, `local_to_map()` / `map_to_local()`을 이용한 좌표 변환이 포함됩니다. 또한 `get_cell_tile_data()`를 통해 타일별 사용자 정의 데이터를 읽고, `set_cells_terrain_connect()`로 자동 타일링(지형)을 구현하며, TileSet의 물리 레이어와 충돌 다각형을 사용한 타일 충돌 감지 방법을 다룹니다. 마지막으로 `CharacterBody2D`의 충돌 지점에서 타일 좌표를 찾거나, 코드에서 `TileSet`을 동적으로 생성하는 방법, 그리고 기존 `TileMap` 코드를 `TileMapLayer`로 마이그레이션하는 방법을 제공합니다.

지원 대상~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/ziva-sh/godot-skills/tree/HEAD/skills/godot-tilemaplayer

Installed? Explore more 코딩 & 개발 skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

즐겨 사용하는 AI에게 물어보기

이 에이전트 스킬이 미리 로드된 새 채팅을 엽니다.

문서

TileMapLayer (Godot 4.3+)

Godot 4.3에서 TileMapLayer 노드가 추가되었으며 TileMap은 더 이상 사용되지 않습니다(Deprecated). 각 TileMapLayer는 하나의 레이어이므로, 바닥, 벽, 장식이 있는 레벨은 하나의 TileSet을 공유하는 세 개의 형제 TileMapLayer 노드로 구성됩니다. TileMap에 대해 새 코드를 작성하지 말고, Godot 3 API(set_cellv, world_to_map, set_cell(x, y, tile_id))를 절대 사용하지 마세요.

셀 API

셀은 정수 맵 좌표(Vector2i)로 식별됩니다. 타일은 세 가지 값으로 식별됩니다.

  • source_id: TileSet에 있는 소스의 ID(아틀라스 텍스처 또는 씬 컬렉션). 첫 번째 아틀라스는 보통 0입니다. TileSet 편집기나 TileSet.add_source()의 반환 값을 확인하세요.
  • atlas_coords: 해당 아틀라스 내 타일의 열과 행(픽셀이 아닌 타일 단위).
  • alternative_tile: 대칭 이동 또는 회전된 대안을 만들지 않았다면 0입니다.
extends TileMapLayer

const SOURCE_ID := 0
const GRASS := Vector2i(0, 0)
const WALL := Vector2i(1, 0)


func _ready() -> void:
	for x in range(10):
		set_cell(Vector2i(x, 5), SOURCE_ID, GRASS)
	set_cell(Vector2i(3, 4), SOURCE_ID, WALL)

	var source_id := get_cell_source_id(Vector2i(3, 4))  # 셀이 비어 있으면 -1
	var atlas := get_cell_atlas_coords(Vector2i(3, 4))   # 비어 있으면 Vector2i(-1, -1)
	print(source_id, atlas)

	erase_cell(Vector2i(3, 4))
	print(get_used_cells().size(), " cells, bounds ", get_used_rect())


func cell_at_global(global_point: Vector2) -> Vector2i:
	return local_to_map(to_local(global_point))


func center_of_cell(coords: Vector2i) -> Vector2:
	# map_to_local은 이 레이어의 로컬 공간에서 셀 중심을 반환합니다.
	return to_global(map_to_local(coords))

중요한 사실:

  • 기본 인수로 set_cell(coords)를 호출하면 셀이 지워집니다(source_id의 기본값은 -1). 타일을 배치할 때는 항상 source_id와 atlas_coords를 전달하세요.
  • 아틀라스에 존재하지 않는 atlas_coords를 설정하면 오류 없이 셀이 저장되지만(get_cell_source_id()는 소스를 반환), 이후 get_cell_tile_data()는 The TileSetAtlasSource atlas has no tile at (x, y). 로그를 출력하고 null을 반환합니다.
  • local_to_map()과 map_to_local()은 레이어의 로컬 공간에서 작동합니다. 레이어가 이동 또는 크기 조정된 경우 to_local() / to_global()로 변환하세요.
  • get_used_cells_by_id(source_id, atlas_coords)는 하나의 타일을 사용하는 모든 셀을 찾습니다.
  • 변경 사항은 프레임 끝까지 일괄 처리됩니다. 충돌 또는 씬 타일을 즉시 업데이트해야 하는 경우 update_internals()를 호출하세요.

타일별 사용자 정의 데이터

TileSet에 사용자 정의 데이터 레이어를 추가하고(Inspector > TileSet > Custom Data Layers, 예: int 타입의 damage), TileSet 편집기에서 값을 칠한 다음 읽습니다:

extends TileMapLayer


func damage_at(coords: Vector2i) -> int:
	var data := get_cell_tile_data(coords)
	if data == null:
		return 0
	return data.get_custom_data("damage")

get_cell_tile_data()는 빈 셀과 씬 컬렉션 타일에 대해 null을 반환하므로 메서드를 호출하기 전에 확인하세요.

지형(자동 타일링)

Godot 3의 자동 타일 비트마스크는 지형 세트가 되었습니다. TileSet에서 지형 세트와 지형을 추가한 다음, TileSet 편집기에서 각 타일의 지형 연결 비트를 칠합니다. 코드에서는 채우려는 모든 셀을 전달합니다:

extends TileMapLayer

const TERRAIN_SET := 0
const DIRT := 0


func paint_room(rect: Rect2i) -> void:
	var cells: Array[Vector2i] = []
	for x in range(rect.position.x, rect.end.x):
		for y in range(rect.position.y, rect.end.y):
			cells.append(Vector2i(x, y))
	set_cells_terrain_connect(cells, TERRAIN_SET, DIRT)

set_cells_terrain_connect()는 가장자리가 연결되도록 타일을 선택합니다. set_cells_terrain_path()는 경로로 그려진 도로와 강을 위한 것입니다. 결과에 잘못되었거나 누락된 타일이 표시되면 TileSet의 연결 비트가 불완전한 것입니다. 코드로는 수정할 수 없습니다.

충돌

TileSet에 물리 레이어(TileSet 인스펙터 > Physics Layers > Add Element)가 있고 타일에 해당 레이어의 충돌 다각형(TileSet 편집기, 타일 선택, Physics > Physics Layer 0; 전체 타일 사각형은 F 키)이 있는 경우에만 타일이 충돌합니다. 레이어의 collision_enabled 속성은 기본적으로 켜져 있습니다. 물리 레이어는 또한 collision_layer와 collision_mask를 가지며, 노드가 아닌 TileSet에서 설정합니다.

CharacterBody2D가 어떤 타일에 닿았는지 찾으려면 충돌 지점을 사용하세요. get_coords_for_body_rid()는 physics_quadrant_size가 1이 아닌 이상(기본적으로 Godot 4.5+는 최대 16x16 셀을 하나의 바디로 병합) 셀의 좌표가 아닌 물리 사분면의 좌표를 반환합니다:

extends CharacterBody2D

@export var level: TileMapLayer


func _physics_process(delta: float) -> void:
	velocity += get_gravity() * delta
	move_and_slide()
	for i in get_slide_collision_count():
		var collision := get_slide_collision(i)
		if collision.get_collider() == level:
			# 충돌 지점이 타일 가장자리에 있으므로 타일 안쪽으로 약간 들어갑니다.
			var inside := collision.get_position() - collision.get_normal()
			var coords := level.local_to_map(level.to_local(inside))
			print("Touching tile ", coords)

코드로 TileSet 구축하기

절차적 레벨과 TileSet 편집기를 사용할 수 없는 테스트에 유용합니다. 충돌 다각형 점은 타일 중심을 기준으로 합니다.

extends Node2D


func _ready() -> void:
	var tile_set := TileSet.new()
	tile_set.tile_size = Vector2i(16, 16)
	tile_set.add_physics_layer()

	var source := TileSetAtlasSource.new()
	source.texture = load("res://tiles.png") as Texture2D
	source.texture_region_size = Vector2i(16, 16)
	source.create_tile(Vector2i(0, 0))
	var source_id := tile_set.add_source(source)

	var data := source.get_tile_data(Vector2i(0, 0), 0)
	data.add_collision_polygon(0)
	data.set_collision_polygon_points(0, 0, PackedVector2Array([
		Vector2(-8, -8), Vector2(8, -8), Vector2(8, 8), Vector2(-8, 8),
	]))

	var layer := TileMapLayer.new()
	layer.tile_set = tile_set
	add_child(layer)
	layer.set_cell(Vector2i(0, 0), source_id, Vector2i(0, 0))

TileMap에서 마이그레이션

에디터에서: TileMap을 선택하고, TileMap 하단 패널을 열고, 도구 상자 아이콘을 클릭한 다음 "Extract TileMap layers as individual TileMapLayer nodes"를 선택합니다. 그런 다음 스크립트를 업데이트합니다: layer 인덱스를 사용하던 모든 TileMap 메서드는 해당 레이어의 노드에서 인덱스 없이 메서드가 됩니다.

이전 코드TileMapLayer
tile_map.set_cell(0, coords, source_id, atlas_coords)ground.set_cell(coords, source_id, atlas_coords)
tile_map.get_cell_source_id(1, coords)walls.get_cell_source_id(coords)
tile_map.get_used_cells(0)ground.get_used_cells()
tile_map.set_layer_enabled(2, false)decoration.enabled = false
tile_map.set_layer_z_index(1, 5)walls.z_index = 5
Godot 3 set_cellv(pos, id), world_to_map(p), map_to_world(c)set_cell(coords, source_id, atlas_coords), local_to_map(p), map_to_local(c)

흔한 실수

  • 픽셀 위치를 set_cell()에 전달하는 것. 먼저 local_to_map()으로 변환하세요.
  • 하나의 숫자(tile_index)로 set_cell(coords, tile_index)을 호출하는 것: 두 번째 인수는 소스 ID이며 atlas_coords는 기본값이 Vector2i(-1, -1)이므로 셀이 지워집니다.
  • 물리 레이어가 없거나 칠해진 다각형이 없는 타일에서 충돌이 발생할 것으로 예상하는 것.
  • 기본 physics_quadrant_size에서 get_coords_for_body_rid()를 사용하여 사분면 좌표를 얻는 것.
  • null 확인 없이 get_cell_tile_data()의 메서드를 호출하는 것.
  • 오래된 튜토리얼 때문에 새 작업에 TileMap 노드를 추가하는 것. 레이어당 하나의 TileMapLayer를 사용하세요.

Individual skills in this repo

This repo contains 4 individual skills — each has its own dedicated page.

ziva-sh/godot-4-api-pitfalls

Fixes Godot 3 APIs and GDScript syntax that AI assistants write into Godot 4 projects, such as KinematicBody2D, move_and_slide(velocity), export, onready, setget, yield, string connect(), instance(), rand_range, the Tween node, File, change_scene, Spatial, rect_* properties, Pool*Array, OS time functions and the old TileMap API. Use when writing, reviewing or porting GDScript for Godot 4.x, when a script fails with "not declared", "not found in base", "was removed in Godot 4" or "is not present

ziva-sh/godot-control-layout

Builds Godot 4 Control UIs that resize instead of clipping or overlapping - containers versus anchors, anchor presets from code, size flags, custom_minimum_size, MarginContainer margins, Label wrapping, mouse_filter, CanvasLayer HUDs, Godot 4 theme override names (add_theme_color_override and friends) and the display/window/stretch settings for multiple resolutions. Use when creating or fixing menus, HUDs, dialogs and inventory screens, when UI elements are cut off, zero-sized, overlapping, igno

ziva-sh/godot-scene-organization

Structures Godot 4 projects so scenes stay reusable and references do not break - when to make a scene, a script or a Resource, instancing with @export PackedScene, preload and load, @onready and %UniqueName node access, _ready order, groups, autoloads, class_name, and resource UIDs with the .uid files added in Godot 4.4, including how to move or rename files safely. Use when creating new scenes or scripts, deciding how nodes find each other, adding global state or an event bus, moving or renami

ziva-sh/godot-signals

Godot 4 signal patterns and their failure modes - declaring typed signals, emit(), connect() and disconnect() with Callables, bind() and unbind(), lambdas, CONNECT_ONE_SHOT and CONNECT_DEFERRED, await on signals and timers, editor-made connections stored in .tscn files, and the call down, signal up rule. Use when wiring UI buttons, timers, Area2D or body events and custom game events, when replacing Godot 3 connect("signal", self, "method") or yield code, or when debugging "already connected", "

관련 스킬