How to know when a node has been effectively freed?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By genete
:warning: Old Version Published before Godot 3 was released.

I have one node that should be freed upon a button click and immediately I need that a new fresh instance of that node would be inserted on the scene again:

func _on_Button_pressed():
	get_node("Piezas").queue_free()
	var piezas=load("res://piezas/escenas/piezas.tscn")
	var piezas_inst=piezas.instance()
	piezas_inst.set_name("Piezas")
	add_child(piezas_inst, true)
	pass

But it always insert “Piezas 2” instead of “Piezas” as node name. This makes me think that “Piezas” node is still at tree.

How should I proceed to eliminate a node and immediately (as soon as possible) insert a new instance of it in the scene with exactly the same name?

:bust_in_silhouette: Reply From: Zylann

You can design your code so you know the node is deleted, or not have it depend on its name. It can be done by keeping the node in a variable and setting this variable to null once you queue free the node, so its name doesn’t matter because you just need to check the variable without using get_node.

:bust_in_silhouette: Reply From: genete

Found the solution myself:

func _on_Button_pressed():
	call_deferred("insertar_piezas")
	pass

func insertar_piezas():
	get_node("Piezas").free()
	var piezas=load("res://piezas/scenas/piezas.tscn")
	var piezas_inst=piezas.instance()
	piezas_inst.set_name("Piezas")
	add_child(piezas_inst, true)
    pass

Just do the steps in a deferred way.

You can also do that indeed, but beware of the .free() on the node, you can’t call this at anytime unless you know what you’re doing :slight_smile:

Zylann | 2017-01-27 18:10

its better to use queue_free, when u use free i could cause an crash. i think when something is accessing it for example.

ingo_nikot | 2017-01-27 18:19

Yep. The node will hang out for a frame when you queue_free(). So it keeps it’s name in the scene tree until it’s cleaned up, the deferred call is a good way around that.

avencherus | 2017-01-27 19:41

You can check the RID too, but the best is not to rely on a name, use a group instead, that will be always the same, and use index -1 for the last element just in case the first was not removed yet.

eons | 2017-01-27 21:04

@Zylann, @ingo_nikot: According to documentation, call_deferred is executed on idle time, so there is not risk calling to free(). See Singletons example.

@eons: groups is an option if I only want to remove the code and insert the new one, but I need to access the rest of the members of the node in other parts of the code for what groups is not an option.

genete | 2017-01-27 22:09

:bust_in_silhouette: Reply From: jandrewlong

This might work:

func _on_Button_pressed():
    get_node("Piezas").set_name("PiezasFreeing")
    get_node("PiezasFreeing").queue_free()

    var piezas=load("res://piezas/escenas/piezas.tscn")
    var piezas_inst=piezas.instance()
    piezas_inst.set_name("Piezas")
    add_child(piezas_inst)

That solution simply works and it is the obviously solution! Aye!

genete | 2017-01-27 22:10