A object wont queue_free() even though its meeting the requirments!

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

I have a fps game where I want to switch guns around at the moment I have it so it spawns the desired gun but when switching its suppost to queue_free() the current weapon and then spawn the other weapon but for what ever reason it doesnt queue_free it and just leaves both weapons on screen!

here is the code its short so you dont have to look through pages! :

:bust_in_silhouette: Reply From: avencherus

I would recommend against freeing and reinstancing smaller objects that are not proving to be a performance issue in memory, and go with hiding and showing them, and skip their processing where it still might be active.

The reason is, that while instancing can be fast enough that it might not interfere with your frame’s budget, adding nodes to the tree sometimes isn’t. It can sometimes eat up a lot of frame time for just a couple of nodes, causing a game to stutter a few frames.

The problem in this snippet is that the variables used to hold the weapons are local. There is no memory of the previous references. So it looks like its creating ~60 instances of each weapon a second.

These are orphaned instances, and when you run long enough the game should get overloaded and come to a halt. They’re not in the tree, so you won’t see them.

Check your orphan count. In the montiors or via code: Performance.get_monitor (Performance.OBJECT_ORPHAN_NODE_COUNT)

The weapons being seen are the ones being added to the SceneTree, which happen only when a button is just pressed. Of the two instances, during input one is added to the tree, and the other is freed. These are references to the previous weapons.

What you’re likely seeing are previously leaked instance, not the failure of queue_free() to free nodes.

If you go with this instancing/freeing approach, managing some variables at a higher scope would solve the problem.

# v3.2.4 (Psuedo-code)

const UNARMED = 0

var current_slot : int = UNARMED
var current_weapon : Node

func _process(delta):

	if(Input.is_action_just_pressed("slot 1") and current_slot != 1):
		swap_weapon(1, glock)

	if(Input.is_action_just_pressed("slot 2") and current_slot != 2):
		swap_weapon(2, usp)


func swap_weapon(p_slot : int, p_weapon : PackedScene) -> void:
	
	current_slot = p_slot

	if( current_weapon):
		current_weapon.queue_free()

	current_weapon = p_weapon.instance()
	add_child(current_weapon)

Hello, thanks for the comment, I seem to understand a bit more now, you mentioned using hiding and showing them does this has the same affect as queue_free() because In the future I plan on making the weapons having their own scripts and if its hidden does the scripts not activate? though now that I think about it I could add an if statement suggesting if visible then do this… would this be correct?

Dragon20C | 2020-11-11 10:09

Off the top of my head, visibility mostly affects rendering. I think certain physics behaviors stop, and GUI elements stop capturing input. Things like that, but mostly what is in the scripts are just functions and execute as they are called. I don’t recall of anything that disables a script, other than removing it from the node. node.set_script(null). I suppose it depends on what is meant.

Everything else is too difficult to speculate as it depends on your final game. When you have something approaching what you want, you’ll have to probe it and step through the logic to know for sure.

Since they’ll have scripts attached, if you don’t get the desired behavior entirely from a single built-in method, you can always write your own enable() / disable() methods that handle things specifically to your needs. Hide / show nodes, enable / disable physics bodies, start / stop processing, etc.

avencherus | 2020-11-11 12:37