Quick answer: Make sure the Area2D’s collision_mask includes the bit set in the body’s collision_layer, the Area’s monitoring is true, both nodes have a CollisionShape2D with an actual Shape resource, and you’re connected to body_entered (not area_entered) for PhysicsBody2D overlaps.

You set up a pickup Area2D, walk the player into it, nothing happens. The signal connection is wired in the editor, the function is correct, the player is visibly inside the area. The problem is one of three layer/mask/monitoring settings.

The Symptom

Player enters the Area2D and body_entered does not emit. No error. Other Area2Ds in the scene work fine.

What Causes This

For an Area2D to detect a body, three things must all be true:

  1. The body’s collision_layer shares at least one bit with the Area’s collision_mask.
  2. Both nodes have a CollisionShape2D (or CollisionPolygon2D) with a non-null Shape resource.
  3. The Area’s monitoring property is true.

For Area-to-Area, also: the other Area’s monitorable must be true, and you must connect to area_entered, not body_entered.

The Fix

Step 1: Set up layers per role. Project Settings → General → Layer Names → 2D Physics. Name the bits:

Layer 1: Player
Layer 2: Enemy
Layer 3: Pickup
Layer 4: Wall

Step 2: Configure the player. Player CharacterBody2D → Collision → collision_layer = Player (bit 1). collision_mask = Wall (bit 4) so the player collides with walls.

Step 3: Configure the pickup. Pickup Area2D → Collision → collision_layer = Pickup (bit 3). collision_mask = Player (bit 1) so the area detects the player.

Step 4: Confirm shapes exist. The CollisionShape2D under each node must have a Shape resource assigned (RectangleShape2D, CircleShape2D, etc.). A bare CollisionShape2D with empty Shape detects nothing.

Step 5: Wire the signal.

extends Area2D

func _ready() -> void:
    body_entered.connect(_on_body_entered)

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

Diagnosing in the Editor

Run the scene with Debug → Visible Collision Shapes turned on. Both colliders should be visible as cyan outlines and overlap visibly. If they don’t overlap visually, the shape sizes are wrong. If they overlap but the signal still doesn’t fire, layers are mismatched.

Add a one-line print at the top of the callback. If it doesn’t print on overlap, the signal isn’t firing — not your callback logic.

Body vs Area

Common mistake: another Area2D drifts into the pickup zone, you expect body_entered to fire. It doesn’t — Areas are not bodies. Connect area_entered in addition if you need to detect both.

area.body_entered.connect(_on_body)
area.area_entered.connect(_on_area)

Spawning Inside the Area

If a body spawns already overlapping an Area, body_entered does not fire retroactively. Use get_overlapping_bodies() in _ready to handle pre-existing overlaps explicitly.

“Layer matches mask. Shape resources set. Monitoring on. body_entered for bodies, area_entered for areas.”

Related Issues

For collision shape not visible, see collision shape debug. For layers being confusing, see collision layers explainer.

Layer-mask-shape-monitoring. Four checks. Signal fires.