+1 vote

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?

in Engine by (674 points)
edited by

3 Answers

+1 vote
Best answer

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)
by (326 points)
selected by

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

0 votes

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.

by (27,170 points)
+1 vote

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.

by (674 points)

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 :)

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

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.

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.

@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.

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.

Categories