Godot Collision Layers and Masks Explained Without the Headache

Learn Godot collision layers and masks with a practical 2D setup. Understand what objects are, what they detect, and how to debug collisions that refuse to fire.

Godot collision layers and masks shown as gameplay physics rules

Collision layers and masks are not hard, but the names make them feel like a trap. The moment a coin stops detecting the player or a bullet hits another bullet, it is tempting to start clicking random checkboxes. That usually makes the project worse.

The practical rule is this: layer means what I am, and mask means what I look for. Once that sentence sticks, Godot collision setup becomes much calmer. If you want the larger body-type overview first, open the Godot Physics guide or the longer Godot physics tutorial.

Layer Means What I Am

Every physics object in Godot can belong to one or more collision layers. Think of layers as labels the physics server can check quickly. A player might be on the Player layer. Enemies might be on the Enemy layer. Walls might be on the World layer.

  • Layer 1 - World: floors, walls, one-way platforms, and tile collisions.
  • Layer 2 - Player: the player character and sometimes player sensors.
  • Layer 3 - Enemy: enemies, enemy hurtboxes, and enemy bodies.
  • Layer 4 - Pickup: coins, health, keys, and level triggers.
  • Layer 5 - Projectile: bullets, arrows, thrown objects, and temporary hits.

You can name these layers in Project Settings so the Inspector shows readable labels instead of anonymous numbers. Do that early. Future-you will not remember that layer 7 meant hazard sensors.

Mask Means What I Detect

The collision mask is the other half. It tells the object which layers it cares about. A player body usually detects World and Enemy. A pickup Area2D usually detects Player. A player bullet might detect Enemy and World, but not Player or Pickup.

gdscript
# Example: configure a pickup Area2D in code.
# In the editor, naming layers is easier. This shows the idea.
extends Area2D

const PLAYER_LAYER := 2

func _ready() -> void:
    collision_layer = 1 << 3 # Pickup layer, if using layer 4
    collision_mask = 1 << (PLAYER_LAYER - 1)
    body_entered.connect(_on_body_entered)

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

Most of the time, set layers in the Inspector instead of code. Code is useful for spawned objects, temporary sensors, or tests, but visual setup is easier to audit.

A Simple 2D Prototype Setup

For a small 2D prototype, start with fewer layers than you think you need. Add more only when two object types need different rules.

  • Player CharacterBody2D: layer Player, mask World + Enemy + Pickup.
  • Enemy CharacterBody2D: layer Enemy, mask World + Player.
  • Coin Area2D: layer Pickup, mask Player.
  • Wall StaticBody2D: layer World, mask usually empty unless it needs detection.
  • Player Bullet Area2D: layer Projectile, mask Enemy + World.

This pairs well with the 2D platformer tutorial: make the player, coin, and level as separate scenes, then assign layers as part of each scene's setup.

Debugging Collisions That Do Not Fire

When a signal does not fire, do not rewrite the script first. Debug the physical setup. Godot collision bugs are often missing shapes, disabled monitoring, or mismatched masks.

  • Turn on Debug > Visible Collision Shapes and confirm the shapes are where you think they are.
  • Check that the Area2D has Monitoring enabled.
  • Check that the target object is on a layer included in the detector's mask.
  • Make sure you connected body_entered for physics bodies and area_entered for areas.
  • Use groups like player or enemy after detection, not as a replacement for collision rules.

The Mental Model to Keep

Layer is identity. Mask is interest. If you keep those two words separate, collision setup stops feeling magical and starts feeling like a readable rule table.