บทนำ

Godot 4 ได้เขียนระบบ TileMap ขึ้นใหม่ทั้งหมด หากคุณเคยใช้ TileMap ใน Godot 3 แทบทุกอย่างจะเปลี่ยนไป — ทั้งตัวแก้ไข TileSet, วิธีการนิยามกระเบื้อง, การปูกระเบื้องอัตโนมัติ, เลเยอร์ และ GDScript API คู่มือนี้จะอธิบายสถาปัตยกรรมใหม่ตั้งแต่เริ่มต้น

สำหรับผู้ใช้ Godot 3: autotile, set_cellv() และ cell_size แบบเดิมถูกยกเลิกไปทั้งหมดแล้ว ดูหัวข้อ การย้ายจาก Godot 3 ที่ด้านล่างของหน้า

สถาปัตยกรรม TileMap ใหม่

ระบบ TileMap ของ Godot 4 ประกอบด้วยสององค์ประกอบหลัก:

  • โหนด TileMap — โหนดที่คุณเพิ่มเข้าไปในฉาก มันเก็บเลเยอร์หนึ่งเลเยอร์ขึ้นไป และอ้างอิงถึงรีซอร์ส TileSet
  • รีซอร์ส TileSet — นิยามตัวกระเบื้องเอง ประกอบด้วยแหล่ง (แอตลาส, คอลเลกชันฉาก ฯลฯ), เลเยอร์ฟิสิกส์, เลเยอร์นำทาง, เลเยอร์ข้อมูลกำหนดเอง และเทอร์เรนเซต

การเปลี่ยนแปลงสำคัญ: ใน Godot 3 ขนาดกระเบื้องถูกกำหนดที่โหนด TileMap ส่วนใน Godot 4 ขนาดกระเบื้องถูกนิยามไว้ในรีซอร์ส TileSet และ TileMap เพียงแค่อ้างอิงถึงมันเท่านั้น

แหล่งของ TileSet

TileSet หนึ่งตัวสามารถมีได้หลายแหล่ง โดยแต่ละแหล่งจะถูกระบุด้วย source_id (จำนวนเต็ม) ประเภทของแหล่งได้แก่:

  • TileSetAtlasSource — ประเภทที่พบบ่อยที่สุด เป็นภาพเท็กซ์เจอร์ภาพเดียวที่บรรจุกระเบื้องหลายอันจัดเรียงเป็นกริด
  • TileSetScenesCollectionSource — กระเบื้องแต่ละอันคือฉากที่แพ็กไว้ มีประโยชน์สำหรับกระเบื้องที่เคลื่อนไหวหรือโต้ตอบได้

การตั้งค่า TileSet

ขั้นตอนที่ 1: สร้างรีซอร์ส TileSet

  1. เพิ่มโหนด TileMap เข้าไปในฉากของคุณ
  2. ใน Inspector ให้คลิกที่พร็อพเพอร์ตี Tile Set แล้วเลือก New TileSet
  3. กำหนด Tile Size (เช่น 16x16 หรือ 32x32)

ขั้นตอนที่ 2: เพิ่มแหล่งแอตลาส

  1. คลิกที่ TileSet เพื่อเปิดตัวแก้ไข TileSet ที่แผงด้านล่าง
  2. คลิกปุ่ม + แล้วเลือก Atlas
  3. ลากภาพไทล์เซตของคุณเข้าไปในพร็อพเพอร์ตี Texture
  4. ตัวแก้ไขจะแบ่งภาพออกเป็นกระเบื้องโดยอัตโนมัติตามขนาดกระเบื้องของคุณ คุณสามารถปรับพื้นที่เท็กซ์เจอร์และระยะขอบได้

ขั้นตอนที่ 3: กำหนดค่าพร็อพเพอร์ตีของกระเบื้อง

ในตัวแก้ไข TileSet คุณสามารถเพิ่มเลเยอร์ประเภทต่าง ๆ ที่ใช้กับกระเบื้องทั้งหมดได้:

  • Physics Layers — รูปทรงคอลลิชันสำหรับกระเบื้อง
  • Navigation Layers — รูปหลายเหลี่ยมที่เดินผ่านได้สำหรับการค้นหาเส้นทาง
  • Custom Data Layers — ข้อมูลแบบกำหนดชนิดตามอำเภอใจ (bool, int, float, String ฯลฯ)
  • Terrain Sets — สำหรับการปูกระเบื้องอัตโนมัติ (ตัวแทนของ autotile ใน Godot 3)

เลเยอร์ของ TileMap

โหนด TileMap เดียวสามารถบรรจุได้หลายเลเยอร์ นี่คือการปรับปรุงครั้งใหญ่เมื่อเทียบกับ Godot 3 ซึ่งคุณต้องใช้โหนด TileMap แยกกันสำหรับพื้นหลังและพื้นหน้า แต่ละเลเยอร์สามารถมีการตั้งค่า 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 และพารามิเตอร์ที่สี่คือ atlas_coords ในรูปแบบ Vector2i

ระบบเทอร์เรน (การปูกระเบื้องอัตโนมัติ)

ระบบเทอร์เรนมาแทนที่ autotile ของ Godot 3 มันจะเลือกกระเบื้องรูปแบบที่ถูกต้องโดยอัตโนมัติตามกระเบื้องข้างเคียง

การตั้งค่าเทอร์เรน

  1. ใน TileSet ให้เพิ่ม Terrain Set (Inspector → Terrain Sets → Add Element)
  2. เลือกโหมดเทอร์เรน: Match Corners and Sides (47 กระเบื้อง), Match Corners (16 กระเบื้อง) หรือ Match Sides (16 กระเบื้อง)
  3. เพิ่มประเภทเทอร์เรนภายในเซต (เช่น "Grass", "Dirt", "Water")
  4. ในตัวแก้ไข TileSet ให้สลับไปที่โหมด Select เลือกกระเบื้อง แล้วระบายบิตการเชื่อมต่อเทอร์เรน (peering bits) บนกระเบื้องแต่ละอัน

การระบายเทอร์เรน

เมื่อกำหนดค่าเทอร์เรนเรียบร้อยแล้ว ให้สลับไปที่ตัวแก้ไข TileMap และเลือกแท็บ Terrains เลือกประเภทเทอร์เรนของคุณแล้วระบายลงบนแผนที่โดยตรง Godot จะเลือกกระเบื้องรูปแบบที่ถูกต้องให้โดยอัตโนมัติ

# Set terrain programmatically
tilemap.set_cells_terrain_connect(0, [Vector2i(5, 3)], 0, 0)
# Parameters: layer, cells array, terrain_set, terrain index

ฟิสิกส์บนกระเบื้อง

วิธีเพิ่มคอลลิชันให้กับกระเบื้อง:

  1. เพิ่ม Physics Layer ใน Inspector ของ TileSet
  2. กำหนดค่าว่าเลเยอร์ฟิสิกส์นี้ใช้คอลลิชันเลเยอร์และมาสก์ใด
  3. ในตัวแก้ไข TileSet ให้สลับไปที่แท็บ Physics แล้ววาดรูปหลายเหลี่ยมคอลลิชันบนกระเบื้องแต่ละอัน

เคล็ดลับ: คุณสามารถมีเลเยอร์ฟิสิกส์หลายเลเยอร์สำหรับกระเบื้องประเภทต่าง ๆ ได้ เช่น เลเยอร์หนึ่งสำหรับกำแพง (ขัดขวางการเคลื่อนที่) และอีกเลเยอร์สำหรับอันตราย (กระตุ้นความเสียหายผ่านการซ้อนทับของ Area2D)

ข้อมูลกำหนดเองบนกระเบื้อง

เลเยอร์ข้อมูลกำหนดเองช่วยให้คุณแนบข้อมูลเมทาดาทาแบบกำหนดชนิดกับกระเบื้องใด ๆ ก็ได้ ซึ่งมีประโยชน์อย่างยิ่งสำหรับตรรกะของเกมเพลย์

การตั้งค่าข้อมูลกำหนดเอง

  1. ใน Inspector ของ TileSet ให้เพิ่ม Custom Data Layer
  2. ตั้งชื่อ (เช่น "is_destructible") และกำหนดชนิดข้อมูล (เช่น bool)
  3. ในตัวแก้ไข 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: bool
  • damage: int
  • movement_cost: float
  • tile_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 Sets)
หนึ่งเลเยอร์ต่อโหนด TileMap หลายเลเยอร์ใน TileMap เดียว
TileMap.tile_set = preload(...) กำหนดรีซอร์ส TileSet ใน Inspector หรือผ่านโค้ด
world_to_map() local_to_map()
map_to_world() map_to_local()

ข้อผิดพลาดที่พบบ่อย

  1. ลืมสร้าง TileSet ก่อน โหนด TileMap จะไม่แสดงตัวแก้ไขกระเบื้องจนกว่าคุณจะกำหนดรีซอร์ส TileSet ให้ สร้างมันขึ้นมาใน Inspector

  2. source_id ผิด หากคุณมีแหล่งแอตลาสเพียงแหล่งเดียว source_id ของมันคือ 0 เมื่อเพิ่มแหล่งที่สอง มันจะได้ source_id = 1 ตรวจสอบแผงด้านล่างของตัวแก้ไข TileSet — แท็บของแต่ละแหล่งจะแสดง ID ของมัน

  3. สับสนระหว่าง atlas_coords กับ tile ID ใน Godot 4 ไม่มี tile ID แบบง่ายอีกต่อไป แต่คุณจะอ้างอิงกระเบื้องด้วยตำแหน่งในกริดแอตลาสในรูปแบบ Vector2i(column, row) แทน

  4. ไม่ระบุพารามิเตอร์เลเยอร์ ทุกการดำเนินการกับเซลล์ต้องมีดัชนีเลเยอร์เป็นอาร์กิวเมนต์แรก การลืมมันจะทำให้เกิดข้อผิดพลาดของอาร์กิวเมนต์

  5. ใช้ set_cellv() เมธอดนี้ไม่มีอยู่แล้ว ให้ใช้ set_cell() ด้วยลายเซ็นแบบใหม่