이거 Godot에서 저도 당했고, 다들 언젠가 한 번은 당하는 것 같아요. emit_signal()이나 signal.emit()은 연결된 함수를 그 자리에서 바로 불러요. 보내는 쪽 호출 안에서, 보내는 쪽의 다음 줄이 돌기 전에요. 프레임 끝까지 기다리는 메시지가 아니라 단계가 좀 더 붙은 함수 호출이에요.
그래서 health_changed 핸들러가 노드를 트리에서 빼거나, 보내는 쪽이 돌고 있는 배열을 고치면 그 일이 보내는 쪽 로직 한가운데서 벌어져요. 핸들러를 나중에 돌리고 싶으면 CONNECT_DEFERRED로 연결하세요. 그러면 호출이 유휴 시간으로 미뤄져요.
나머지 절반은 프레임 단위 로직을 어디에 두느냐예요. _process(delta)는 렌더링되는 프레임마다 한 번씩, 들쭉날쭉한 delta로 돌아요. _physics_process(delta)는 프로젝트 설정의 고정 물리 틱 속도로 돌고요. CharacterBody2D를 _process에서 움직이면 대체로 잘 되다가 프레임 속도가 달라지면 다르게 굴어요. 이동과 물리 단계가 더는 발을 맞추지 않으니까요.
지금 제 규칙은 충돌이 걸린 이동은 _physics_process, 화면 쪽은 _process, 핸들러가 씬 트리를 바꿀 수 있으면 지연 연결이에요. 마지막 걸 기본으로 해야 할지는 솔직히 모르겠어요. 전부 지연시키면 이벤트 순서를 따라가기가 더 어려워지거든요.
