Warum Kollisions-Layer wichtig sind

Kollisions-Layer sind die Grundlage aller Physik-Interaktionen in Godot 4 — Bewegung, Trefferabfrage, Raycasting, Area-Trigger und mehr. Den Unterschied zwischen Layer und Mask zu verstehen ist entscheidend, und ihn misszuverstehen ist einer der häufigsten Stolpersteine für Einsteiger wie auch erfahrene Entwickler.

Layer vs. Mask — Das mentale Modell

Jedes Physik-Objekt in Godot hat zwei Bitmask-Eigenschaften:

Grundregel

A kollidiert mit B, wenn A's Mask B's Layer enthält ODER B's Mask A's Layer enthält. Nur eine Seite muss die andere „sehen", damit eine Kollision auftritt.

Layer in den Projekteinstellungen benennen

Bevor du irgendeinen Code schreibst, benenne deine Layer. Das macht den Inspector deutlich einfacher zu nutzen und verhindert Verwirrung, wenn dein Projekt wächst.

Projekteinstellungen > Layer-Namen > 2D-Physik (oder 3D-Physik):

Layer-Nr. Name Zweck
1PlayerDie Spielerfigur
2EnemyAlle Gegner-Körper
3EnvironmentWände, Böden, Plattformen
4ProjectileGeschosse, Pfeile, Zauber
5PickupItems, Münzen, Heilpakete
6TriggerSensoren, Spawn-Zonen, Checkpoints

Layer im Code setzen (GDScript)

Godot 4 bietet zwei Ansätze — die wertbasierte API (empfohlen) und die direkte Bitmask-Zuweisung:

# 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)

Bitmask-Falle

Layer-Nummern sind bei set_collision_layer_value() 1-basiert, aber die zugrunde liegende Bitmask ist 0-basiert. Layer 1 = Bit 0 = Wert 1, Layer 2 = Bit 1 = Wert 2, Layer 3 = Bit 2 = Wert 4. Im Zweifel nutze die wertbasierte API, um Fehler zu vermeiden.

Gängige Layer-Schemata

Platformer / Side-Scroller

Objekt Layer Mask Erklärung
Player12, 3, 5, 6Erkennt Gegner, Umgebung, Pickups, Trigger
Enemy21, 3Erkennt Spieler und Umgebung
Environment3Passiv — wird von anderen erkannt
Projectile42, 3Trifft Gegner und Wände
Pickup5Passiv — der Spieler erkennt es
Trigger61Erkennt nur den Spieler

Top-Down / Roguelike

Objekt Layer Mask Erklärung
Player12, 3, 5, 6Erkennt Gegner, Wände, NPCs, Sensoren
Enemy21, 3Erkennt Spieler und Wände
Wall3Passiv
Bullet41, 2, 3Trifft Spieler, Gegner und Wände
NPC53Kollidiert nur mit Wänden
Sensor61Erkennt das Betreten durch den Spieler

Area2D / Area3D Layer

Areas nutzen dasselbe Layer/Mask-System. Zusätzlich haben sie zwei Umschalt-Eigenschaften:

Signale: area_entered vs. body_entered

body_entered wird ausgelöst, wenn ein PhysicsBody (CharacterBody, RigidBody, StaticBody) die Area betritt. area_entered wird ausgelöst, wenn eine andere Area sie betritt. Achte darauf, für deinen Anwendungsfall das richtige Signal zu verbinden.

# 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()

RayCast Kollisionsmaske

RayCast-Nodes haben nur eine Mask (keinen Layer), weil sie Detektoren und keine physischen Körper sind. Setze die Mask, um zu filtern, was der Strahl treffen kann:

# 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

Praktisches Beispiel: Player – Enemy – Projectile

Hier ist ein vollständiges Layer-Setup für ein typisches Action-Spiel. Kommentare zeigen die Überlegung hinter jeder Entscheidung:

# 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

Tipp: Friendly-Fire verhindern

Beachte, dass Player-Bullets Layer 2 (Enemy) maskieren, aber nicht Layer 1 (Player), und Enemy-Bullets Layer 1 (Player) maskieren, aber nicht Layer 2 (Enemy). So verhinderst du Friendly-Fire rein durch die Layer-Konfiguration — ganz ohne Code.

Debugging-Tipps

Migrationsänderungen 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)
bit-Parameter war 0-basiert layer-Parameter ist 1-basiert
20 Layer verfügbar 32 Layer verfügbar

Migrations-Stolperstein

Wenn du ein Godot-3-Projekt portierst, denke daran, dass set_collision_layer_bit(0, true) zu set_collision_layer_value(1, true) wird. Der Index verschiebt sich um +1. Übersiehst du das, sind alle deine Layer um eins verschoben.

Häufige Fehler

1. Vergessen, die Mask zu setzen

Dein Objekt hat einen Layer, aber die Mask ist leer (alles Nullen). Das Objekt existiert in der Physikwelt, erkennt aber nichts. Andere Objekte mit passenden Masken erkennen es weiterhin, aber move_and_slide() auf diesem Objekt geht durch alles hindurch.

2. Layer mit Mask verwechseln

Den Layer des Spielers auf 2 (Enemy) setzen statt seine Mask. Jetzt ist der Spieler ein Gegner, soweit es die Physik-Engine betrifft. Merke dir immer: Layer = was ich bin, Mask = was ich scanne.

3. Bitmask-Werte statt Layer-Nummern verwenden

set_collision_layer_value(4, true) schreiben in dem Glauben, es setze den Bitmask-Wert 4 (Layer 1+2). In Wirklichkeit aktiviert es Layer 4. Die wertbasierte API nimmt Layer-Nummern, keine Bit-Werte.

4. Einseitige Erkennung, wo Beidseitigkeit erwartet wird

Objekt A maskiert B's Layer, aber B maskiert nicht A's Layer. move_and_slide() auf A kollidiert mit B, aber move_and_slide() auf B geht durch A hindurch. Damit sich zwei CharacterBody-Nodes gegenseitig blockieren, müssen beide den Layer des anderen in ihrer Mask haben.

Physik-Setup mit Godot MCP Pro automatisieren

Schluss mit dem manuellen Umschalten von Layer-Kontrollkästchen. Lass die KI dein gesamtes Kollisions-Setup in Sekunden konfigurieren — inklusive Layer-Benennung, Masken-Zuweisung und dem Hinzufügen von Raycasts.

Godot MCP Pro holen — $15
Zugehörige Werkzeuge: setup_collision set_physics_layers get_physics_layers get_collision_info add_raycast