• Godot HelpProgramming
  • emit_signal will not emit with arguments added, except when signal is connected through Godot GUI

Hi, new to Godot here and first time asking a question, and it's a bit complicated....

I am attempting to connect a signal using code, from a child to its parent node, and have the signal pass an argument. The reason I want to use code and not the Godot GUI is that I am iterating a number of these children (game pieces) and the child scene is not in the tree before runtime (I don't know of any reason why it should be?).

The real issue isn't the iterating of the children, because I am totally successful connecting signals in code from my instanced children to the parent. The problem is that emit_signal(), which is working for those children, does nothing once I add an argument in that line, using the correct format. I don't get an error, but the signal does not emit.

When I set everything up in the child and parent to pass the argument, and simply don't add an argument to emit_signal(), there's no error: it emits a signal. In the parent, it seems to pass a value from the signal connection to the function, but the value that's passed to the function is Null.

But if I add the argument to emit_signal(), it does not emit a signal at all.

I created a fresh test tree for this issue and was able to recreate it, even with the child scene being in the tree from the beginning, confirming the issue occurs even in that case.

But this way I could use the GUI to connect the signal. As soon as I did that, the entire process worked correctly and the argument was passed with the signal. So the issue was not whether the child scene was in the tree, but just that it gets connected through the GUI.

After using the GUI, the connection is not written in the script. It calls the automatic function that the GUI creates, but I'm pretty sure I'm using the correct format when I code my own connection and function in the parent node: it's taken from reading every discussion I could find online, and I confirmed it not only by trying just about every small variation on the format, but by the fact that only in this format does the connected function even get called.

Any ideas on how I can get this working right? I know I could come up with a workaround but I would like to get the signal working fully. Thanks!

The full code of "childnode":

		extends Node2D
		
		var helens = 30
		
		signal chosen
		# This also works with chosen() 
		# And writing chosen(helens) will autofill helens as a variable 
		# in the signal dock, but doesn't affect this
		
		func _ready():
			pass
		
		func _unhandled_key_input(event):
			if Input.is_key_pressed(16777221):
				print("pressed ENTER")
				emit_signal("chosen", helens) 
				# This will not emit a signal with the argument here.
				# It also doesn't work in other formats 
				#  such as emit_signal("chosen", 30)
				#  or different argument types
				#  It only emits as emit_signal("chosen") 

The full code of the parent node:

		extends Node2D
		
		func _ready():
			var helens
			$childnode.connect("chosen", self, "_test_signal", [helens])
			pass
			
		func _test_signal(helens):
			print("test function called from ", helens)

So, if I remove the 'helens' argument from the emit_signal line, this prints "test function called from Null" . If I retain the helens argument in emit_signal, it prints nothing.


If I use the GUI to connect the signal to the parent node, I can have 'helens' in the emit_signal line. I just have to add it to the parameters of the function that the GUI created in the parent node. The connection and function I coded manually still work, but aren't triggered if the argument is in the emit line.

Once it's connected by GUI, the parent node looks like this:

		extends Node2D
		
		func _ready():
			var helens
			$childnode.connect("chosen", self, "_test_signal", [helens])
			pass
			
		func _test_signal(helens):
			print("test function called from ", helens)
		
		func _on_childnode_chosen(helens):
			print("GUI function called from ", helens)

This will print "GUI function called from 30"

I'm quite new to Godot as well, but if it's any help I tried tinkering a bit with your code. if you just leave out the argument [helens] out of this line, it seems to work.

$childnode.connect("chosen", self, "test_signal", [helens]) becomes $childnode.connect("chosen", self, "test_signal",)

I was able to print out "test function called from 30", by pressing enter.

I'm not sure if it helps, but it's something.

edit: Doh, maybe check to see if the signal is connected before you emit it?

get_parent().get_signal_connection_list("signal name") should return an array of connections

The parameter should only be when you call it. Not when you connect the signal.

Hmm, from docs:

connect("pressed", self, "_on_Button_pressed") # BaseButton signal
connect("text_entered", self, "_on_LineEdit_text_entered") # LineEdit signal
connect("hit", self, "_on_Player_hit", [ weapon_type, damage ]) # User-defined signal

emit_signal("hit", weapon_type, damage)
emit_signal("game_over")

connect("hit", self, "_on_Player_hit", [ weapon_type, damage ]) # weapon_type and damage are passed last
emit_signal("hit", "Dark lord", 5) # "Dark lord" and 5 are passed first
func _on_Player_hit(hit_by, level, weapon_type, damage):
    print("Hit by %s (lvl %d) with weapon %s for %d damage" % [hit_by, level, weapon_type, damage])

https://docs.godotengine.org/en/stable/classes/class_object.html#class-object-method-connect https://docs.godotengine.org/en/stable/classes/class_object.html?#class-object-method-emit-signal

@cybereality said: The parameter should only be when you call it. Not when you connect the signal.

If so then the docs seem to be wrong...

That parameter array on signal definition is for variables that are added after the ones you pass in when emitting. They are optional and not needed (maybe there is a good use, I haven't needed them yet). For example:

signal do_print

func _ready():
	connect("do_print", self, "print_something", [789])
	emit_signal("do_print", "I'm a String", 123)

func print_something(string, num1, num2):
	print(string + " " + str(num1) + " " + str(num2))

Which prints:

I'm a String 123 789

But you can also do it like this and add as many parameters as you like, without defining them first on the connect function:

signal do_print

func _ready():
	connect("do_print", self, "print_something")
	emit_signal("do_print", "I'm a String", 123, 456, "I'm done")

func print_something(string1, num1, num2, string2):
	print(string1 + " " + str(num1) + " " + str(num2) + " " + string2)

Which prints:

I'm a String 123 456 I'm done

@Megalomaniak said: If so then the docs seem to be wrong...

No, the docs are correct. They are just explaining a more advanced usage that is not what the OP in this thread is asking about.

Ah thanks so much!! At first, adding the parameter in connect() was the only thing that would call the function, so I wasn't attempting anything without it after that. I guess it makes sense that after adding a parameter in connect(), the function isn't being called correctly if an argument is also added to emit without taking both into account. But could not figure out what was going wrong. Thank you so much for the help!

2 years later