2
\$\begingroup\$

I want to delete a scene and re-load it. This code would fail later, because the new "CoolScene" has in fact a different name, something like "@NotSuchCoolName@34", and thus it cannot be referenced with $CoolScene once the garbage collector destroys the old scene:

$CoolScene.queue_free()
var cool_node = load("res://pathto/CoolScene.tscn").instance()
add_child(cool_node )
cool_node.set_name("CoolScene")

But if I rename the scene, then it will work:

$CoolScene.set_name("oldCoolScenebyebye")
$oldCoolScenebyebye.queue_free()
var cool_node = load("res://pathto/CoolScene.tscn").instance()
add_child(cool_node)
cool_node.set_name("CoolScene")


$CoolScene.whatever #Works now!

However this looks like awful code to me, main reason being that I need to invent temp names that are unique everytime a scene gets deleted, something that should be done by the garbage collector. Please help me write better code!

\$\endgroup\$

1 Answer 1

0
\$\begingroup\$

Let us look that this code:

$CoolScene.queue_free()
var cool_node = load("res://pathto/CoolScene.tscn").instance()
add_child(cool_node)
cool_node.set_name("CoolScene")

The first line $CoolScene.queue_free() will delete the Node referenced by $CoolScene. But not yet. See also What is happening during queue_free() process? - Suffice to say that Godot will remove the Node from the scene tree, and free it sometime after the code finished executing, and no, that isn't a garbage collector.

The second and third line instantiates and adds a new child Node. Be aware that at this point, this new Node will already have a name. Godot would have generated a new name if it collided with the name of the existing Node.

And finally the fourth line would change the name of the Node. Except it still cannot have that name because the existing node still has it.


To fix that we are going to separate removing a Node from the scene tree and freeing it.

var old_node = $CoolScene
remove_child(old_node)

var cool_node = load("res://pathto/CoolScene.tscn").instance()
add_child(cool_node)

old_node.queue_free()

Here the first line var old_node = $CoolScene is keeping a reference to the old node in a variable so I can call queue_free on it at the end.

The second line remove_child(old_node) removes it from the scene tree.

Now the third and fourth lines can instantiate and add the new node. Which can have its expected name - right away (we didn't have to wait until the old Node was freed) and without issue - since the old node is not in the scene tree anymore.

Finally the fifth line calls queue_free on the old node, which can be deleted sometime later also with no issue.

And, of course, we didn't have to come up with some other name.

\$\endgroup\$
1
  • \$\begingroup\$ Thank you, I should have thought about that as well! Very well explained too \$\endgroup\$
    – grokkaine
    Feb 18, 2022 at 17:15

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .