Dlaczego warstwy kolizji są ważne

Warstwy kolizji są podstawą wszystkich interakcji fizycznych w Godot 4 — ruchu, wykrywania trafień, raycastingu, wyzwalaczy Area i nie tylko. Zrozumienie różnicy między Layer a Mask jest kluczowe, a jej niezrozumienie to jeden z najczęstszych problemów zarówno dla początkujących, jak i dla doświadczonych deweloperów.

Layer vs Mask — Model myślowy

Każdy obiekt fizyczny w Godot ma dwie właściwości typu bitmaska:

Podstawowa zasada

A koliduje z B, gdy maska A zawiera warstwę B LUB maska B zawiera warstwę A. Wystarczy, że tylko jedna strona „widzi" drugą, aby doszło do kolizji.

Nazywanie warstw w ustawieniach projektu

Zanim napiszesz jakikolwiek kod, nazwij swoje warstwy. Dzięki temu inspektor jest znacznie łatwiejszy w użyciu i unikniesz zamieszania, gdy projekt się rozrośnie.

Ustawienia projektu > Nazwy warstw > Fizyka 2D (lub Fizyka 3D):

Nr warstwy Nazwa Przeznaczenie
1PlayerPostać gracza
2EnemyWszystkie ciała przeciwników
3EnvironmentŚciany, podłogi, platformy
4ProjectilePociski, strzały, zaklęcia
5PickupPrzedmioty, monety, apteczki
6TriggerCzujniki, strefy spawnu, punkty kontrolne

Ustawianie warstw w kodzie (GDScript)

Godot 4 oferuje dwa podejścia — API oparte na wartościach (zalecane) oraz bezpośrednie przypisanie bitmaski:

# Godot 4 API — value-based (1-indexed, recommended)
set_collision_layer_value(1, true)   # I am on layer 1
set_collision_mask_value(2, true)    # I detect layer 2

# Or use bitmask directly
collision_layer = 1   # Layer 1 only (bit 0)
collision_mask = 6    # Layers 2 and 3 (bits 1 + 2 = 6)

# Read current state
var on_layer_1: bool = get_collision_layer_value(1)
var scans_layer_2: bool = get_collision_mask_value(2)

Pułapka bitmaski

Numery warstw w set_collision_layer_value()liczone od 1, ale leżąca u podstaw bitmaska jest liczona od 0. Warstwa 1 = bit 0 = wartość 1, warstwa 2 = bit 1 = wartość 2, warstwa 3 = bit 2 = wartość 4. W razie wątpliwości używaj API opartego na wartościach, aby uniknąć błędów.

Typowe schematy warstw

Platformówka / Side-scroller

Obiekt Layer Mask Wyjaśnienie
Player12, 3, 5, 6Wykrywa przeciwników, otoczenie, przedmioty, wyzwalacze
Enemy21, 3Wykrywa gracza i otoczenie
Environment3Pasywne — wykrywane przez innych
Projectile42, 3Trafia przeciwników i ściany
Pickup5Pasywne — gracz je wykrywa
Trigger61Wykrywa tylko gracza

Top-down / Roguelike

Obiekt Layer Mask Wyjaśnienie
Player12, 3, 5, 6Wykrywa przeciwników, ściany, NPC, czujniki
Enemy21, 3Wykrywa gracza i ściany
Wall3Pasywne
Bullet41, 2, 3Trafia gracza, przeciwników i ściany
NPC53Koliduje tylko ze ścianami
Sensor61Wykrywa wejście gracza

Warstwy Area2D / Area3D

Area używa tego samego systemu Layer/Mask. Dodatkowo posiada dwie właściwości przełączane:

Sygnały: area_entered vs body_entered

body_entered uruchamia się, gdy do Area wchodzi PhysicsBody (CharacterBody, RigidBody, StaticBody). area_entered uruchamia się, gdy wchodzi inna Area. Upewnij się, że podłączasz właściwy sygnał do swojego przypadku użycia.

# Pickup Area2D — detect when the Player body enters
func _ready() -> void:
    body_entered.connect(_on_body_entered)

func _on_body_entered(body: Node2D) -> void:
    if body.is_in_group("player"):
        collect()
        queue_free()

Maska kolizji RayCast

Węzły RayCast mają tylko Mask (bez Layer), ponieważ są detektorami, a nie ciałami fizycznymi. Ustaw maskę, aby filtrować to, w co promień może trafić:

# RayCast that only detects enemies (layer 2)
$RayCast2D.collision_mask = 2  # Layer 2 = Enemy
# Or use the value-based API:
$RayCast2D.set_collision_mask_value(1, false)  # Ignore Player
$RayCast2D.set_collision_mask_value(2, true)   # Detect Enemy
$RayCast2D.set_collision_mask_value(3, false)  # Ignore Environment

# Line-of-sight ray that ignores projectiles
$LineOfSight.collision_mask = 0
$LineOfSight.set_collision_mask_value(1, true)  # Player
$LineOfSight.set_collision_mask_value(3, true)  # Environment

Praktyczny przykład: Player – Enemy – Projectile

Oto kompletna konfiguracja warstw dla typowej gry akcji. Komentarze pokazują tok rozumowania stojący za każdą decyzją:

# Player (CharacterBody2D)
# Layer: 1 (Player)          — "I am the player"
# Mask: 2 (Enemy), 3 (Environment), 5 (Pickup)
#   — I collide with enemies, walls, and can pick up items

# Enemy (CharacterBody2D)
# Layer: 2 (Enemy)            — "I am an enemy"
# Mask: 1 (Player), 3 (Environment)
#   — I collide with the player and walls

# Player Bullet (Area2D)
# Layer: 4 (Projectile)       — "I am a projectile"
# Mask: 2 (Enemy), 3 (Environment)
#   — I hit enemies and walls, but NOT the player who fired me

# Enemy Bullet (Area2D)
# Layer: 4 (Projectile)       — "I am a projectile"
# Mask: 1 (Player), 3 (Environment)
#   — I hit the player and walls, but NOT the enemy who fired me

Wskazówka: zapobieganie friendly fire

Zauważ, że pociski gracza maskują warstwę 2 (Enemy), ale nie warstwę 1 (Player), a pociski przeciwników maskują warstwę 1 (Player), ale nie warstwę 2 (Enemy). W ten sposób zapobiegasz friendly fire wyłącznie poprzez konfigurację warstw — bez żadnego kodu.

Wskazówki do debugowania

Zmiany migracyjne Godot 3 → 4

Godot 3 Godot 4
set_collision_layer_bit(bit, value) set_collision_layer_value(layer, value)
set_collision_mask_bit(bit, value) set_collision_mask_value(layer, value)
Parametr bit był liczony od 0 Parametr layer jest liczony od 1
20 dostępnych warstw 32 warstwy dostępne

Pułapka migracji

Jeśli przenosisz projekt z Godot 3, pamiętaj, że set_collision_layer_bit(0, true) staje się set_collision_layer_value(1, true). Indeks przesuwa się o +1. Jeśli to przeoczysz, wszystkie Twoje warstwy będą przesunięte o jeden.

Częste błędy

1. Zapomnienie o ustawieniu maski

Twój obiekt ma warstwę, ale maska jest pusta (same zera). Obiekt istnieje w świecie fizyki, ale niczego nie wykrywa. Inne obiekty z pasującymi maskami wciąż go wykryją, ale move_and_slide() na tym obiekcie będzie przenikać przez wszystko.

2. Mylenie Layer z Mask

Ustawienie Layer gracza na 2 (Enemy) zamiast jego Mask. Teraz gracz jest przeciwnikiem z punktu widzenia silnika fizyki. Zawsze pamiętaj: Layer = czym jestem, Mask = co skanuję.

3. Używanie wartości bitmaski zamiast numerów warstw

Napisanie set_collision_layer_value(4, true) w przekonaniu, że ustawia ono wartość bitmaski 4 (warstwy 1+2). W rzeczywistości włącza to warstwę 4. API oparte na wartościach przyjmuje numery warstw, a nie wartości bitów.

4. Jednokierunkowe wykrywanie tam, gdzie oczekiwane jest dwukierunkowe

Obiekt A maskuje warstwę B, ale B nie maskuje warstwy A. move_and_slide() na A zderzy się z B, ale move_and_slide() na B przeniknie przez A. Aby dwa węzły CharacterBody wzajemnie się blokowały, oba muszą mieć warstwę drugiego w swojej masce.

Automatyzuj konfigurację fizyki z Godot MCP Pro

Przestań ręcznie przełączać pola wyboru warstw. Pozwól AI skonfigurować całe ustawienie kolizji w kilka sekund — w tym nazywanie warstw, przypisywanie masek i dodawanie raycastów.

Zdobądź Godot MCP Pro — $15
Powiązane narzędzia: setup_collision set_physics_layers get_physics_layers get_collision_info add_raycast