Godot Version
Godot 4.x (4.2+)
Question
I was watching a tutorial video in which the author first used queue_free()
in a signal to free a node after the player picked it up, but then he said it was better/safer to use call_deferred("queue_free")
to avoid freeing the node in the middle of a physics tick.
(I assume that queue_free.call_deferred()
is essentially the same thing as call_deferred("queue_free")
but the first one has the benefit of auto-completion and avoiding potential typos due to not using a string. And while personally I would use the first form in my own code, throughout the rest of this post I’ll be using the latter form because that’s how it was shown in the tutorial video.)
The problem is as follows:
I was under the impression that queue_free()
already waited until the end of physics/process frames so using call_deferred("queue_free")
is unnecessarily redundant, essentially accomplishing the same thing that queue_free()
would do on its own.
The author and I engaged each other in the comments and neither of us were entirely confident in our positions. I did some searches to try and find an answer but mostly only found people asking about the difference between queue_free()
and call_deferred("free")
which is an entirely different question.
So then I asked an AI to summarize the difference for me and it said queue_free()
schedules the deletion of the node at the end of the current frame while call_deferred("queue_free")
schedules the deletion of the node at the beginning of the next frame which “allows it to clean up any resources it has allocated” first.
Meanwhile, the official documentation on Callable.call_deferred()
says:
Calls the method represented by this Callable in deferred mode, i.e. at the end of the current frame. Arguments can be passed and should match the method’s signature.
And for Object.call_deferred()
it says:
Calls the method on the object during idle time. Always returns null, not the method’s result.
Idle time happens mainly at the end of process and physics frames. In it, deferred calls will be run until there are none left, which means you can defer calls from other deferred calls and they’ll still be run in the current idle time cycle. If not done carefully, this can result in infinite recursion without causing a stack overflow, which will hang the game similarly to an infinite loop.
Which sounds to me like the AI was wrong (no big surprise there!) and call_deferred("queue_free")
also schedules the deletion of the node at the end of the current frame.
All of that to say that I’m still not sure there’s a practical difference between queue_free()
and call_deferred("queue_free")
.
Is there a difference? And if so, can someone please explain to me what the difference is and under what circumstances one would be preferred over the other?