Signal is not reaching node

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By ExFabian

I am trying to make an infinite scroller game, and I created a signal in the player node that tells the ground and obstacles to stop scrolling when the player dies. It works with the ground node, but for the obstacle node it will stop only if you touch the first spawned in obstacle. If you die from any of the obstacles spawned after, they will keep moving until they despawn at the edge of the screen.
The problem is that every obstacle after the first one doesn’t enter the _on_Player_game_over() function for some reason.

Player code:

func _on_Player_area_entered(_area):
	emit_signal("game_over")
	$AnimatedSprite.animation = "lost"
	lost = true

Obstacle spawning mechanism (located in main node):

func _on_cactusSpawnTimer_timeout():
	randomize()
	t = rand_range(0,1) #change with score
	yield(get_tree().create_timer(t),"timeout")
	var cactus = cactus_scene.instance()
	add_child(cactus)

func _on_Player_game_over():
	$cactusSpawnTimer.stop()

Obstacle code:

func _ready():
	position.y = yPos
	position.x = xPos

func _process(_delta):
	if xPos > 0:
		xPos -= speed * 1.33
	else:
		queue_free()
	position.x = xPos

func _on_Player_game_over():
	speed = 0

I am wondering how you connected the obstacle to the signal, since there is no connect function in _ready().
(I think we don’t need to call randomize() at each timeout, since it changes the whole RNG table.)

toxicvgl | 2022-10-25 10:39

I connected it using the editor from the Player node properties in the Node tab. Should I have connected it using code?

ExFabian | 2022-10-25 16:24

Thank you, I didn’t know the editor works like that.
Then I guess your first cactus is in the scene, and you are creating its instances. I don’t know how the editor gets the player nodepath and when it connects the signal, but the problem may be here.

toxicvgl | 2022-10-25 18:37

That explains why only the first one returned the function, however the instances still don’t detect the signal at all

ExFabian | 2022-10-25 20:14

You mean even if you connect by code? Adding player.connect("game_over", cactus, "_on_Player_game_over") after add_child() should work in my theory…(I think it is useful if game_over is a global signal)

toxicvgl | 2022-10-25 21:53

That worked, thanks! I didn’t know global signals were a thing.

ExFabian | 2022-10-26 06:17

Glad you solved! About “global signals” (actually I don’t know how everyone calls it), I refer to this great tutorial: https://www.youtube.com/watch?v=yRHN_WEulLc

If it’s too long: If you have a signal game_over in an autoloaded node (singleton) GameEvent, then you can emit this from anywhere by GameEvent.emit_signal("game_over"), and connect to it (GameEvent.connect("game_over", cactus, "_on_Player_game_over"))

toxicvgl | 2022-10-26 07:46

:bust_in_silhouette: Reply From: toxicvgl

For now, the problem can be solved by connecting signals through codes.
Adding player.connect("game_over", cactus, "_on_Player_game_over") after add_child() should work, if the spawner knows the player node.

The problem here is that we are not sure how the editor connects signals of new instances, or even whether instances remember such signals. I opened up a question here: Connecting signals through editor, translated in GDScript - Archive - Godot Forum