Hi! (I think) I ran into some issues where child nodes aren't quite ready yet when the parent wants to do some stuff, so I'm trying to yield until they are.

Now I have a weird situation with yield that's waiting for a ready signal. With a node that's already in the scene tree it works:

var node = get_node( myNodePath )
yield( node, 'ready' )
print( node.name, ' is ready' ) # <--- all good, this gets executed after the node's _ready

However, if I create a node by instantiating a PackedScene the ready signal doesn't seem to fire, or yield just can't hear it. I do add it as a child to the current scene because it seems that this needs to happen to run the node's _ready function.

var node = myPackedScene.instance()
add_child( node ) # <--- I do see the new node in the scene
yield( node, 'ready' )
print( node.name, ' is ready' ) # <--- code execution never reaches here

I tried to add a custom signal to the PackedScene node instead, emit it at the end of _ready and changed the yield to listen to the custom signal. But it's the same situation, code execution never gets past that yield. It doesn't seem to "hear" the signal from the instantiated PackedScene.

From the docs: the _ready callback is called in reverse order, starting with the children and moving up to the parent nodes This means that when adding a node to the scene tree, the following order will be used for the callbacks: _enter_tree of the parent, _enter_tree of the children, _ready of the children and finally _ready of the parent (recursively for the entire scene tree).

So you need to listen for tree_entered instead. Or you should use call_deferred to add the child.

Thanks for the reply @Jatz .

I tried to listen for the tree_entered signal, but it's the same and doesn't go past the yield. I double-checked to print something in _init, _enter_tree and _ready and the functions get called in this order.

However, I'm getting more and more convinced that it really is my problem to understand what is going on in what order. I'm looping through a couple of children that were added as regular scene nodes using the GUI scene tree or via code as PackedScenes that get initialised and then added as children. But I think my mistake is that I assume the yield is waiting for a signal that gets fired after the code reaches the yield. But in fact it gets fired before the code even gets to the yield, and so the yield will wait forever (literally Waiting for Godot). That's why even custom signals didn't work.

In the end I could solve the issue without any yield. But the issue and your response helped me to understand when happens what.

It's a bit lengthy, but if anyone is interested: In my code I added an export var with a dictionary that I write into the node's metadata. That gives me a lot of flexibility to add any custom variables through the GUI.

export ( Dictionary ) var metaData: Dictionary

I write this into the meta data (there is a reason why I want this accessible via get_meta and not the custom export property metaData):

func write_meta_data() -> void:
	for key in metaData.keys():
		set_meta( String( key ), metaData[ String( key ) ] )

For me the interesting bit was, that for my purposes calling write_meta_data() must happen in _enter_tree(). In _init() the metaData values entered in the node inspector don't seem to be there yet, so that's pointless. In _ready() it does write the meta data, however, in _ready it's too late if a parent node wants to access and do something with that data. Useful but not if the metadata needs to get accessed from outside. In _enter_tree() it works as expected, the export var data gets written into the metadata and the parent can read the newly written data.

2 years later