How to recieving signals from coded instances of scenes?

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

Hello,

I am new to the godot engine and new to game enginiering. I have done the your first game in the documentation . Based on that I wanted to program a “Flappy Bird” clone. I am now having problems connecting the signals. My scenes look like this:

Main
Player
HUD
Wall

This is the main-scene code:

onready var Wall = preload("res://Wall.tscn")

func _ready():
	randomize()
	get_tree().get_root().find_node("Wall", true, false).connect("lose_game", self , "_on_Wall_lose_game()")

func _on_Wall_lose_game():
	get_tree().reload_current_scene()

func _on_WallSpawTimer_timeout():
	$WallPath/WallSpawnLocation.offset = randi()
	var wall = Wall.instance()
	add_child(wall)
	wall.position = $WallPath/WallSpawnLocation.position

As you can see, the timer spawns the wallparts every one second. This works fine.

This is the wall-scene code:

extends Node2D

var screen_size
var velocity = Vector2()
signal get_point
signal lose_game

# Called when the node enters the scene tree for the first time.
func _ready():
	screen_size = get_viewport_rect().size
		
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
	velocity.x = -150
	position += velocity*delta
	if position.x < 0:
		queue_free()


func _on_UpperWall_area_entered(area):
	emit_signal("lose_game")
	print("hit oben")

func _on_LowerWall_area_entered(area):
	emit_signal("lose_game")
	print("hit unten")

func _on_Score_area_exited(area):
	emit_signal("get_point")
	print("punkt")

The wall-scene should transmit two signals:

  • “lose_game” when the upper-wall-collision or the lower-wall-collision gets triggerd. This should be connected with the main scene and restart the game.
  • “get_point” when the score-collision is triggerd. This should be connected to the HUD-scene and update the label.

The print-methods works fine so I assume that the singals are sent.

At last, this is the HUD-scene code:

extends Node2D

# Declare member variables here. Examples:
var score = 0
# var b = "text"


# Called when the node enters the scene tree for the first time.
func _ready():
	get_tree().get_root().find_node("Wall", true, false).connect("get_point",self, "handle_get_point")


func handle_get_point():
	score += 1
	$ScoreLabel.text = str(score)
	print(score)

The documentation says to connect the nodes with the signals in the ready_function. I have already tested some variations (e.g. $Wall.connect(“get_point”,self, “handle_get_point”), get_Node(“Wall”).connect(…), get_tree().get_root().find_node(“Wall”, true, false).connect(…)) but nothing seems to connect the signals correctly.

When im using $Wall.connect("lose_game", self , "_on_Wall_lose_game()") this error appear:

E 0:00:00.610   get_node: (Node not found: "Wall" (relative to "/root/Main").)
  <C++ Error>   Condition "!node" is true. Returned: __null
  <C++ Source>  scene/main/node.cpp:1371 @ get_node()
  <Stack Trace> Main.gd:8 @ _ready()

When using Wall.connect("lose_game", self , "_on_Wall_lose_game()") this one appear:

E 0:00:00.598   connect: In Object of type 'PackedScene': Attempt to connect nonexistent signal 'lose_game' to method 'Node2D._on_Wall_lose_game()'.
  <C++ Error>   Condition "!signal_is_valid" is true. Returned: ERR_INVALID_PARAMETER
  <C++ Source>  core/object.cpp:1500 @ connect()
  <Stack Trace> Main.gd:8 @ _ready()

I guess i am missing something fundamental about the signals but i don´t know what it is. I’ve been looking for answers for the last two days and found a few similar questions but nothing that helped me. So if someone has already asked the same question I would like to apologize in advance and would be glad if someone could help me.

thank you in advance and kind regards

Visterface

:bust_in_silhouette: Reply From: kidscancode

You’re on the right track. Your problem is when you do this:

Wall.connect("lose_game", self , "_on_Wall_lose_game()")

you’re not referring to a node. Wall is your loaded PackedScene that you’re instancing.

$Wall.connect("lose_game", self , "_on_Wall_lose_game()")

There is no node named “Wall”. Because node names must be unique among siblings, the instance you’re creating isn’t named that.

What you want to do is connect each wall’s signal when you instance it and add it to the tree. You have the wall variable, which refers to the instance, and you’re using that to refer to it in order to add it to the tree.

func _on_WallSpawTimer_timeout():
    $WallPath/WallSpawnLocation.offset = randi()
    var wall = Wall.instance()
    add_child(wall)
    wall.position = $WallPath/WallSpawnLocation.position
    wall.connect("lose_game", self , "_on_Wall_lose_game")

Also, when referring to the name of the target method in connect(), you do not include the ().

Thank you very much!! This was the problem and the solution works fine. The game is now running as intended. I really really appreciate you taking the time to help me out!

If someone has a similar problem: To connect the signal of the HUD I used onready var hud = get_node("HUD") and for the connection
wall.connect("get_point", hud , "handle_get_point")
The main scene now looks like this:

extends Node2D

onready var Wall = preload("res://Wall.tscn")
onready var hud = get_node("HUD")

# Called when the node enters the scene tree for the first time.
func _ready():
	randomize()
	

func _on_Wall_lose_game():
	get_tree().reload_current_scene()

func _on_WallSpawTimer_timeout():
	$WallPath/WallSpawnLocation.offset = randi()
	var wall = Wall.instance()
	add_child(wall)
	wall.position = $WallPath/WallSpawnLocation.position
	wall.connect("lose_game", self , "_on_Wall_lose_game")
	wall.connect("get_point", hud , "handle_get_point")

Visterface | 2021-05-31 18:23