This one bit me in Godot and seems to bite everyone eventually. emit_signal() and signal.emit() call the connected functions right away, inside the emitting call, before the emitter's next line runs. It's a function call with extra steps, not a message that waits for the end of the frame.
So when a health_changed handler removes a node from the tree, or modifies the array the emitter is looping over, it does that in the middle of the emitter's logic. If you want the handler to run later, connect with CONNECT_DEFERRED and the call gets queued for idle time instead.
The other half is where per-frame logic lives. _process(delta) runs once per rendered frame with a varying delta. _physics_process(delta) runs at the fixed physics tick rate from the project settings. Moving a CharacterBody2D in _process mostly works, then behaves differently at another frame rate, because movement and the physics step aren't in lockstep anymore.
My current rule is collision-related movement in _physics_process, visuals in _process, and deferred connections whenever a handler might change the scene tree. Not sure that last one should be the default, honestly. Deferred everywhere makes the order of events harder to follow.
