No. Emitting a signal just lets any listeners know that the signal has been emitted, and the emitter carries on with its business. It doesnât wait for a response. If it did wait for a response, then an emiiter with no listeners would be stuck waiting forever.
Thatâs an interesting question. Here is a little test scenario I made, where I am observing the final value of test_variable:
@onready var debug_label = $CanvasLayer/Control/Label
var test_variable : int = 0
signal signal_1
signal signal_2
signal signal_3
func _ready():
signal_1.connect(_on_signal_1)
signal_2.connect(_on_signal_2)
signal_3.connect(_on_signal_3)
firing_signals()
func firing_signals():
signal_1.emit()
signal_2.emit()
signal_3.emit()
func _on_signal_1():
test_variable = 1
func _on_signal_2():
for x in range(100000):
var node = get_child(0)
node.visible = not node.visible #introducing fake lag
test_variable = 2
func _on_signal_3():
test_variable = 3
func _process(_delta):
debug_label.text = str(test_variable)
I ran this very simple test multiple times and the final value of test_variable did turn out to be 3 every time, but this may not happen if your situation is more complicated than this. I added the fake lag spike to see if the processing of 2 would delay the processing of 3, and it did. I think this happened because this is all happening on the same scene so it is handling the reactions to the signals in the order they are emitted. Makes sense, but this test is not really a good use of the signal pattern.
But, if there were multiple different scenes involved spread around the scene tree that were the listeners of the signals, I donât know how reliably you can predict the result of test_variable. Maybe it depends on tree order, maybe it depends on what else is being processed at the moment. Iâm not sure!
In the end though, itâs probably best not to rely on the order of execution of signals. If the order of execution is crucial, then it might be a good idea to refactor what you want to do into a different coding pattern that is more explicitly linear. Or maybe you can create a similar test using a bunch of scenes and let us know how it goes!
No, emit_signal doesnât wait for subscribers to process the signal. It triggers the connected methods and immediately continues with the next line of code, so itâs non-blocking.
As for the order of signals, yes, they are received in the same order they are emitted. Godot ensures that signals are processed sequentially, so if you emit several in a row, theyâll be handled in that order.
Are you sure about this? This and this reddit post as well as my own quick testing seem to suggest otherwise. That is, as long as the signal receiver is synchronous the emitter will only continue after the receivers are done.
Interesting question. According to the first reddit thread, someone actually looked at the code (which is the only way to know for sure, empirical evidence is not adequate), "Yes. I used to think it stored the signals emitted and resolved all the connections later at the end of this loop, but on a hunch I checked the engine code and it actually calls all the connected methods as soon as you emit the signal, and only returns control to your function once everything is done. "
But what he didnât indicate is what happens if there is no pending connect in a wait state? In this case I assume it simply returns and continues on.
Out of interest, I had a quick peek at the source myself. As far as I can tell (Iâm not a C++ programmer), the object keeps a map of all signals and their connected functions. When the signal is emitted, it iterates through the map/list of callables stored for the specific signal and calls them immediately (if not emitted deferred). If there is no receiver connected, the list is empty, no function is called, and the control is returned to the emitter.
Now that I was already looking at the source, I tried to figure out if signals are called in order. As it seems, they are. The signals are stored in a custom HashMap, but it is also partly a LinkedList for iteration. Therefore, they should be called in insertion order (there seems to be an exception for the CONNECT_REFERENCE_COUNTED flag, but I donât know what it does).
That said, take all this with a grain of salt. As Iâve said, Iâm not well-versed in C++, and Iâm not very familiar with the Godot codebase.