0 votes

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 queuefree() the current weapon and then spawn the other weapon but for what ever reason it doesnt queuefree it and just leaves both weapons on screen!

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

https://pasteall.org/oHYb

in Engine by (132 points)

1 Answer

+1 vote
Best answer

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)
by (5,192 points)
selected by

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?

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.

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.