How to connect signal to instances of a scene

Godot Version

Godot Engine v4.2.2.stable.official.15073afe3

Question

I want to connect a signal for when the player dies so that I can show a game over screen. The problem is that there are multiple different objects with the samme KillZone scene in them and I don’t know how I can connect the signal from all the different KillZones without typing in all the paths manually.

Here is what I’ve done so far but it only connects to one of the KillZones
(relevant code is in the _ready() function)

extends CanvasLayer

signal restart

func _ready():
	# Hides game over screen when game starts
	visible = false
	var kill_zone = get_node("/root/Game/KillZone")
	kill_zone.game_over.connect(_on_kill_zone_game_over)

# Start timer to restart game
func _on_restart_button_pressed():
	$Timer.start()

# Restart game at the end of timer
func _on_timer_timeout():
	get_tree().reload_current_scene()

# Quit game
func _on_quit_button_pressed():
	get_tree().quit()


func _on_kill_zone_game_over():
	visible = true

And here is code for emitting the signal in the KillZone:

extends Area2D

signal game_over

# Emits game_over signal when the player enters the area
func _on_body_entered(body):
	print("Player died")
	game_over.emit()

It seems like the killzone is connecting to it’s own event, why not flip the logic on gameover to find the UI for each killzone.

Otherwise you can connect them in-editor one by one, group them and use get_tree().get_nodes_in_group("killzones").

1 Like

I made a group called KillZones and put the KillZone nodes in it but it didn’t work and I got the error: Invalid get index 'game_over' (on base: 'Array[Node]').
Then I tried printing the variable kill_zone and go this which seems to be working:
[KillZone:<Area2D#30299653376>]

Here is the updated code for the game over screen:

extends CanvasLayer

signal restart

func _ready():
	# Hides game over screen when game starts
	visible = false
	var kill_zone = get_tree().get_nodes_in_group("KillZones")
	print(kill_zone)
	kill_zone.game_over.connect(_on_kill_zone_game_over)

# Start timer to restart game
func _on_restart_button_pressed():
	$Timer.start()

# Restart game at the end of timer
func _on_timer_timeout():
	get_tree().reload_current_scene()

# Quit game
func _on_quit_button_pressed():
	get_tree().quit()


func _on_kill_zone_game_over():
	visible = true

(And changing the logic so the killzone isn’t connecting to its own event is a good idea so I will implement it when I get this working)

Read the error. the get_nodes_in_group returns an array: Array[Node]. The print you posted is right, it’s an array with a single KillZone node in it :slight_smile:

Iterate over it with a for loop, that’s what you are looking for

var all_kill_zones = get_tree().get_nodes_in_group("KillZones")
for kz in all_kill_zones:
    kz.game_over.connect(_on_kill_zone_game_over)
2 Likes

It works now but only for the nodes that are in the main scene. The killZones under the “pillars” scene aren’t working.


The Pillars node isn’t inside the main scene, from what I can see. If it’s not loaded in the currently active scene (tree), the query will not see the killzones that aren’t loaded.

Dou you add the pillars scene after start of the game in code?

I just realized - the code I posted is running only once inside the _ready method. Any killzones that are not loaded you will have to connect when spawning them!

1 Like

Yes! It finally works, thank you so much!

1 Like