Меня это укусило в Godot, и, похоже, рано или поздно кусает всех. emit_signal() и signal.emit() вызывают подключённые функции сразу, внутри самого вызова, ещё до следующей строки отправителя. Это вызов функции с лишними шагами, а не сообщение, которое ждёт конца кадра.
Поэтому если обработчик health_changed убирает узел из дерева или меняет массив, по которому отправитель идёт в цикле, это происходит посреди логики отправителя. Чтобы обработчик выполнился позже, подключайте его с CONNECT_DEFERRED, тогда вызов встанет в очередь на время простоя.
Вторая половина вопроса в том, где живёт покадровая логика. _process(delta) выполняется раз за отрисованный кадр с плавающим delta. _physics_process(delta) идёт с фиксированной частотой физических тиков из настроек проекта. Если двигать CharacterBody2D в _process, в основном всё работает, а при другой частоте кадров ведёт себя иначе, потому что движение и шаг физики больше не идут в ногу.
Сейчас правило такое. Движение, связанное со столкновениями, в _physics_process, визуальное в _process, а отложенные подключения там, где обработчик может поменять дерево сцены. Честно, неясно, стоит ли делать последнее поведением по умолчанию. Если откладывать всё подряд, порядок событий становится труднее отследить.
