Quick answer: Use area.set_deferred("monitoring", true), then await get_tree().physics_frame and manually iterate get_overlapping_bodies() to re-trigger your entry logic for bodies already inside.

A trap room disables its damage Area2D while a cutscene plays, then re-enables monitoring when control returns. The player is still standing in the trap — but they take no damage. The body_entered signal never fires because the player was already inside when the area woke up.

Why the Re-Enable Misses Existing Bodies

Area2D’s body_entered is an edge-triggered signal. It fires when a body crosses the boundary into the area. Toggling monitoring off and back on doesn’t reset the “already inside” state — from the physics server’s perspective, the body was inside when monitoring was off, and it remains inside when monitoring resumes. No boundary crossing happened during the on-state, so no entry signal is emitted.

The Fix: Manual Re-Detection

extends Area2D

func pause_for_cutscene():
    self.set_deferred("monitoring", false)

func resume_after_cutscene():
    self.set_deferred("monitoring", true)
    await get_tree().physics_frame
    for body in get_overlapping_bodies():
        _on_body_entered(body)

The set_deferred calls schedule the property changes to apply between physics steps. The await waits for the physics server to rebuild the overlap list under the new state. The for-loop manually invokes your existing entry handler for every body currently inside.

Why set_deferred Matters

If you assign monitoring = true directly from inside a physics callback (e.g., another body_entered handler), Godot may complain “can’t change this state while flushing queries” in the console. The deferred form serializes the change to the next safe point. Adopt it as the default for monitoring/monitorable flag changes.

Symmetric Logic for body_exited

The same issue applies on disable: if you turn monitoring off while a body is inside, body_exited doesn’t fire because the body didn’t actually cross the boundary outward. If your game logic relies on a clean exit when areas disable, emit it manually:

func pause_for_cutscene():
    for body in get_overlapping_bodies():
        body_exited.emit(body)
    self.set_deferred("monitoring", false)

Now downstream listeners see a consistent enter/exit pair regardless of monitoring toggles.

Verifying

Add a counter damage_ticks incremented in _on_body_entered. Stand inside the area, trigger the disable/enable cycle. Before fix: counter increments once initially and never again. After fix: counter increments once initially and once more after the cycle.

“Toggling monitoring doesn’t replay entries. Re-detect existing overlaps manually after re-enable.”

Always pair monitoring toggles with a manual sweep — otherwise pause/resume flows silently desync.