Quick answer: Physics layer and mask are set per PhysicsBody, not inherited from parent scenes. Every RigidBody2D, CharacterBody2D, StaticBody2D, and Area2D needs its collision_layer and collision_mask set explicitly.
You build a boss scene in Godot with a parent Node2D, a child RigidBody2D for the boss hurtbox, and a grandchild Area2D for the damage zone. You set collision layers on the parent and assume everything inherits. Nothing detects anything. The bug is that physics layers are body properties, not scene properties.
Layers vs Masks
Every PhysicsBody has two bitmasks:
- collision_layer: which layers the body occupies (what it is).
- collision_mask: which layers the body detects (what it looks for).
For a collision to happen, body A’s mask must include body B’s layer. The relationship is asymmetric — A can detect B without B detecting A.
The Fix
Step 1: Name your layers. In Project Settings → Layer Names → 2D Physics, set meaningful names: player, enemy, pickup, wall, hurtbox, hitbox. The inspector then shows checkbox labels instead of layer numbers 1-32.
Step 2: Set layer + mask on every body.
# Enemy RigidBody2D
collision_layer = 1 << (LAYER_ENEMY - 1) # this body is on enemy layer
collision_mask = (1 << (LAYER_WALL - 1)) | (1 << (LAYER_PLAYER - 1))
# Player hitbox Area2D (deals damage)
collision_layer = 1 << (LAYER_HITBOX - 1)
collision_mask = 1 << (LAYER_HURTBOX - 1) # only looks for hurtboxes
Step 3: Set in the inspector for scenes. For designer-edited scenes, click the matrix of checkboxes in the inspector. The matrix visualization is much harder to get wrong than bitmask math.
CollisionShape Is Not a Body
A CollisionShape2D/3D has no layer or mask. It only provides geometry. The parent PhysicsBody reads that geometry and applies the body’s own layer/mask. If you put a CollisionShape directly under a plain Node2D, nothing detects it at all.
Verifying the Fix
Enable Debug → Visible Collision Shapes. Every collision shape renders in-game with a cyan outline. If your shape is visible but collisions fail, it’s a layer/mask issue. If the shape is missing, the CollisionShape node is under a non-body parent.
“Godot physics layers do not inherit. Every body is an island that must declare what it is and what it watches for. Get both right and collisions are trivial.”
Related Issues
For Area2D signal problems, see Godot Area2D body_entered signal not firing. For RigidBody2D contact reporting, see Godot RigidBody2D contact monitor not reporting.
Always name your physics layers first. An unnamed matrix of 32 checkboxes is impossible to reason about after two weeks.