Skip to content

Physics Layers

Configure collision layers, masks, and layer names for your project.

Godot's physics layer system uses bitmasks with 32 layers. Each layer has a number (1-32) and can have a human-readable name. Getting these right is critical for correct collision detection — wrong layers are one of the most common sources of "why doesn't this collide?" bugs.

Understanding the layer system

Godot physics bodies have two bitmask properties:

  • collision_layer: "I am on these layers" — which layers this body occupies
  • collision_mask: "I detect these layers" — which layers this body can interact with

Two bodies interact if body A's mask includes body B's layer (or vice versa for mutual detection). This is an AND relationship: the bits must overlap.

Example:

Player:  layer=0b0001 (layer 1), mask=0b0110 (layers 2+3)
Enemy:   layer=0b0010 (layer 2), mask=0b0001 (layer 1)
Wall:    layer=0b0100 (layer 3), mask=0b0000 (no detection)

Player detects Enemies (player mask has layer 2 set) and Walls (player mask has layer 3 set). Enemies detect Players. Walls detect nothing. Enemies do not detect Walls (enemy mask=1, wall layer=4, no overlap).

Operations

physics_set_layer_names

Get or set the display names for collision layers. Names appear in the Godot editor's layer picker.

Get all names:

json
{
  "op": "physics_set_layer_names",
  "project_path": "/home/user/my-game"
}
ParameterTypeRequiredDescription
layer_typestringrequiredWhich layer category to configure. Valid values: "2d_physics", "3d_physics", "2d_render", "3d_render", "2d_navigation", "3d_navigation", "avoidance".
layersobjectrequiredMap of layer number (1-32) to human-readable name. Example: {"1": "player", "2": "enemies", "5": "projectiles"}. Layers not included are left unchanged.
project_pathstringrequiredAbsolute path to the Godot project directory.

Response:

json
{
  "layer_names": {
    "1": "Player",
    "2": "Enemies",
    "3": "World",
    "4": "Pickups",
    "5": "Projectiles",
    "6": "Triggers"
  }
}

physics_set_layers

Set collision layer and mask configuration on nodes.

json
{
  "op": "physics_set_layers",
  "project_path": "/home/user/my-game",
  "scene": "scenes/player.tscn",
  "node": "Player",
  "layers": [1]
}
ParameterTypeRequiredDescription
collision_layernumber optional
default: null
Collision layer bitmask (32-bit unsigned integer). Determines which physics layers this object occupies. Omit to leave unchanged.
collision_masknumber optional
default: null
Collision mask bitmask (32-bit unsigned integer). Determines which physics layers this object scans/detects. Omit to leave unchanged.
node_pathstringrequiredPath to the node within the scene tree (e.g. "Player/CollisionShape2D").
project_pathstringrequiredAbsolute path to the Godot project directory.
scene_pathstringrequiredScene file to modify (relative to project, e.g. "scenes/player.tscn").

Response:

json
{
  "op": "physics_set_layers",
  "node": "Enemy",
  "collision_layer": 2,
  "result": "ok"
}

Layer number to bitmask conversion

Layers activeBitmask
Layer 11
Layer 22
Layers 1+23
Layer 34
Layers 1+35
Layers 2+36
Layers 1+2+37
Layer 48

The formula: bitmask = sum of (2^(layer_number - 1)) for each active layer.

Director accepts both bitmask integers and layer number arrays — use whichever is clearer.

Example conversation: Fixing a detection problem

Bullets are not hitting enemies. I think the collision layers are wrong. Check and fix them.
Enemy: collision_layer=2, collision_mask=1. Bullet scene: the Area3D has collision_layer=8 (layer 4), collision_mask=0. The bullet Area3D has mask=0 — it monitors zero layers, so it will never detect anything. Set bullet Area3D collision_mask to 2 (enemy layer).
Fixed. Bullet HitArea now monitors layer 2 (Enemy). The body_entered signal will fire when the bullet overlaps an enemy. Make sure the signal is connected to a hit handler in the bullet script.

Tips

Name your layers before assigning them. Use physics_set_layer_names to set up a consistent naming scheme (Player, Enemies, World, Projectiles, Triggers). This makes layer assignments readable — "layer 2" means nothing; "Enemies" is clear.

Use the layer list format for readability. "masks": [1, 3] is clearer than "collision_mask": 5. Both work; use whichever is less error-prone.

Layers are 1-indexed in Director, but 0-indexed internally in Godot. When reading collision_layer bitmasks in Godot's GDScript, bit 0 = layer 1. Director uses 1-indexed layer numbers to avoid off-by-one confusion.

Area3D requires monitoring: true. An Area3D with correct collision layers but monitoring=false will never emit body_entered/area_entered. Check this with spatial_inspect if detection is still failing after fixing layers.

Open source under the MIT License.