Quick answer: The most common cause is calling it too early, such as in _ready(), before the physics engine has processed overlaps. Other causes include monitoring being disabled or collision layer/mask mismatches.
Here is how to fix Godot get overlapping bodies returns empty. You set up an Area2D or Area3D with a collision shape, bodies are clearly overlapping it at runtime, but get_overlapping_bodies() keeps returning an empty array. Meanwhile body_entered fires perfectly. This inconsistency comes down to when the physics engine updates its overlap cache and whether monitoring is configured correctly.
The Symptom
You call get_overlapping_bodies() on an Area2D or Area3D and it returns [] even though bodies are visually inside the area. You might be calling it in _ready() to detect bodies already overlapping at scene load, or from a timer callback. The confusing part is that body_entered works — it fires exactly when a body enters. But querying the overlap list programmatically returns nothing.
What Causes This
1. Calling it before the physics frame. This is the most common cause. get_overlapping_bodies() queries the physics server’s internal overlap cache, which only updates during physics ticks. If you call it in _ready(), the physics engine has not processed any frames yet, so the list is empty regardless of spatial positions.
2. Monitoring is disabled. The monitoring property must be true for overlap detection. When false, neither signals nor the overlap query produce results. It defaults to true but can be toggled off accidentally in the Inspector.
3. Collision layer/mask mismatch. The Area’s collision mask must include at least one layer the target body occupies. Without matching bits, the physics engine skips overlap checks entirely.
The Fix
Await a physics frame before querying overlaps. This gives the physics engine time to process the initial collision pass:
extends Area2D
func _ready():
# Wait for physics to process the first frame
await get_tree().physics_frame
var bodies = get_overlapping_bodies()
print("Overlapping bodies: ", bodies.size())
for body in bodies:
print(" - ", body.name)
Alternatively, move the query into _physics_process() where the overlap cache is always current. Also verify monitoring and collision masks:
extends Area2D
func _ready():
monitoring = true
set_collision_mask_value(1, true)
print("Monitoring: ", monitoring)
print("Mask: ", collision_mask)
func _physics_process(_delta):
var bodies = get_overlapping_bodies()
if bodies.size() > 0:
print("Found: ", bodies)
Related Issues
If your Area2D signals also fail to fire, the problem is a layer/mask or monitoring issue rather than timing — see Area2D body_entered signal not firing. If you are building a state machine that depends on overlap queries for transitions, check state machine stuck in wrong state for related timing pitfalls.
If body_entered works but get_overlapping_bodies does not, it is almost always a timing issue. Await the physics frame.