Quick answer: Scenes cannot see each other's nodes reliably, and connections are lost when a scene is freed. Put shared signals on an autoload (an event bus), emit them from anywhere with Events.player_died.emit(), and connect to them in each listener's _ready(). Godot removes the connection automatically when the listener is freed.

The UI needs to know when the player takes damage, but the HUD and the player live in different scenes. Wiring them with get_node("../../Level/Player") works until the tree changes. There are better patterns, and they also fix the "signal stopped working after changing level" bug.

Why direct connections break

A connection is between two specific objects. When change_scene_to_file() frees the old scene, every connection to its nodes goes with it. Paths like get_node("/root/Main/Level/Player") also break the moment someone renames or reparents a node, and fail outright when the target scene is not loaded yet.

Pattern 1: an event bus autoload

Create events.gd:

extends Node

signal player_damaged(amount: int, remaining: int)
signal coin_collected(total: int)
signal level_completed(level_id: String)

Register it under Project Settings > Globals > Autoload with the name Events. Autoloads live for the whole game, above any scene change.

Emit from anywhere:

# player.gd
func take_damage(amount: int):
    health -= amount
    Events.player_damaged.emit(amount, health)

Listen from anywhere:

# hud.gd
func _ready():
    Events.player_damaged.connect(_on_player_damaged)

func _on_player_damaged(_amount: int, remaining: int):
    $HealthBar.value = remaining

Neither scene references the other. When the HUD is freed, its connection is removed automatically.

Pattern 2: connect when you instance

When one scene creates another, it already has the reference, so connect at that moment:

var enemy := EnemyScene.instantiate()
enemy.died.connect(_on_enemy_died)
add_child(enemy)

Pattern 3: groups for broadcasts

To call a method on every member of a set without signals: get_tree().call_group("enemies", "alert", player_position). Good for one-off broadcasts; signals are better for ongoing events with typed arguments.

Common mistakes with an event bus

Related fixes