how can i remove child not every frame (read more for better undestanding)

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By ouhellouder

onready var pistol = get_node_or_null(“Head_position/Glock 2021”)
onready var Pistol = preload(“res://Glock 2021.tscn”).instance()
onready var head_pos = get_node(“Head_position”)

var gun = false
var current_weapon = 1

func weapon_select():
if Input.is_action_just_pressed(“Pistol”):
current_weapon = 1
if Input.is_action_just_pressed(“Sub_machine_gun”):
current_weapon = 2
if Input.is_action_just_pressed(“Shutgun”):
current_weapon = 3
if Input.is_action_just_pressed(“Assult_rifle”):
current_weapon = 4
if Input.is_action_just_pressed(“Sniper_rifle”):
current_weapon = 5
if Input.is_action_just_pressed(“Rocket_launcher”):
current_weapon = 6

if current_weapon == 1 and pistol == null:
	head_pos.add_child(Pistol)
elif current_weapon != 1 and pistol != null :
		pistol.queue_free()

func _process(delta):
weapon_select()

if i run this code ecerything works just fine as long as i dont press other number than 1 after that it shows me “quee_free” in an “null_instance” as long as i understand that code is running every frame so queue free as well i dont know how to make queue_free only once pls help

Did you make sure not to mix up Pistol and pistol?

juppi | 2021-12-03 15:36

im 100% percent sure that i dont mixed them up

ouhellouder | 2021-12-03 15:52

:bust_in_silhouette: Reply From: Inces

There are multiple ways of doing this. I see You tried to use “get_node_or_null” above. Nodes that are queued free don’t immadietely become null, they first become “recently_freed”. In order to detect recently freed node You can call “is_instance_valid”. But You should not do it above in variable introduction, but in the real moment You need to check this. So :

elif current_weapon != 1 and pistol != null :
        if is_instance_valid(pistol):
                pistol.queue_free()

That should do it for now. In the future I would recommend keeping dynamic track of nodes, that are created and freed. For example adding references of them to array when they are instanced, and using this reference later to queue them free. You will have to rethink this once You will think You need more pistols in your game :slight_smile:

well i found some different way to queue_free() it i added

Inside Pistol script:

func _process(delta):
if Global.current_gun != Global.pistol:
self.queue_free()

Inside my Player script:

func weapon_select():
if Input.is_action_just_pressed(“Pistol”):
current_weapon = 1
Global.current_gun = Global.pistol
head_pos.add_child(Pistol_instance)

i also have some onready var:

onready var Pistol = preload(“res://Glock 2021.tscn”)
onready var Pistol_instance = Pistol.instance()
onready var head_pos = get_node(“Head_position”)

it works but like 3 times then it shows error
E 0:00:03.436 add_child: Parameter “p_child” is null.
<C++ Source> scene/main/node.cpp:1160 @ add_child()
Character.gd:39 @ weapon_select()
Character.gd:85 @ _process()
and i dont know why .Could someone be that good and help me thanks for help by the way

ouhellouder | 2021-12-03 19:28

This is not a way to go. This does nothing.
Other ways of calling queue_free() just once :

1.You could call queue_free() once by using boolean value ( true/false). If weapon is not gun and if value is true → queue free gun and set value to false.
2. Setget. This a type od function that executes some code at the moment chosen variable is changed. So if weapon index is changed queue_free former weapon. Read about setget in documentation
3. Signals. Perhaps the most practical and common. Connect gun to "weapon changed " signal so it would queue itself free.

Of course is_instance_valid method I gave You above is most lazy option.
Whatever You will choose, You should take a note - There is no way to call queue_free multiple times and get this error if the node queues ITSELF free.

Inces | 2021-12-03 20:00