Wait, do you want to kill the node and bring it back to the scene ? If so You can’t queue it free. Just use
remove_child(). Such a node will exist away of the scene tree with all of its variables, as long as its hard references are not broken. It can be then childed again, preceded with
About the good practices, I would say - when You are making complicated game, make objects dead instead of deleting them. Like design state : CORPSE, in which your node will reside, with process set to false, raycasts turned off and dead body sprite. All the corpses can be queued free simoultanoulsy on occasion, for example when player enters new room. This is correct way to control removal of objects.
Finally, there is an antidote for arrays filled with deleted objects.
returns true when a node is alive and false when it is just empty reference to something already deleted.
Still it is wiser to manually remove objects from arrays of references whenever You queue any node free
Hi! Thanks a lot for your answer. Those are good insights for sure. I think what you said about the hard references being unbroken is the root of my problem. Ideally I am looking for a way to completely remove all references to the freed node.
Maybe I should have been more specific though on what’s plaguing me. The node I am freeing and then reinstancing is a tilemap node, the current level of the game. I am then using the tilemap’s ready function to parse a config file which determines things about the level such as enemies to spawn etc.
I was experimenting with what would happen if I just freed and reinstanced the tilemap to see if I would be able to create a progressively harder version of it via the config file. The ideal loop would be level is loaded, player beats the level, level is freed and reinstanced, incrementing the completed level tracker, and then its ready function sets it up according to the config file.
And finally when I call remove_child(tilemap) on the tilemap node, the whole game crashes, haha. Maybe the engine doesn’t like when you remove something and then reinstance it immediately.
As I’m typing this out though I am seeing that this is definitely not the right way to go about it, so I think I’ll try to take a little break to shake off the tunnel vision.
BigTuna675 | 2022-06-01 21:25
Yes, freeing a node just to reset it may seem like easiest way to avoid tedious process of recreating it. But it actually is the hardest way, as it requires to tediously ensure, that all other nodes stop depending on it.
I assume You created some tile layout in editor, that changes during project run, and want to assemble it to original on reset. I would advise to keep layout data in some resources or dictionaries and load them as needed. You can also create
toolscript, that will encrypt layout You made in editor into a file or resource.
Also, queuing free wouldn’t be this problematic if it wasn’t for hardcoded references. If You dig into programming practice of “observer pattern”, You will learn how to avoid hard dependencies and make more elastic code, that doesn’t care for changes in scene tree hierarchy.
Ahh yes this is exactly what I was looking for! It’s true that I’ve used quite a few of:
var nodeRef = get_tree().get_nodes_in_group("Target")
which is what I guess created a lot of hard dependencies/references. Glad to hear that using signals (observer pattern) would be a better way to do that. I’ll still need to get some kind of a reference to the emitter/receiver to connect the signal but that should still de-spaghettify the code a bit.
I’ll mark your answer as accepted now. I know the simplest way to fix this is going to be to create a fakeReset() function that will reset the level without actually freeing and reinstancing it. I was just curious as to why I was getting such weird behaviour, because it was not very intuitive at first. Or at least I didn’t know that you need to manually deal with nulling out references to freed nodes to prevent this weird zombie behaviour.
Moving forward I guess I’ll try to avoid getting hard references to things that are not within the immediate scene if I can avoid it, or at least will intentionally null them once they’ve served their purpose. Cheers!
BigTuna675 | 2022-06-02 15:59
To finish I will give You ultimate tip, that was a huge bliss for me :
You can define all signals in Autoload,
listeners will call Autoload.connect()
emitters will call Autoload.emit_signal()
This way everything is connected without hard references
Ohhh that is very interesting. Yes that certainly changes how I might go about dealing with these sorts of things, thanks a bunch!
BigTuna675 | 2022-06-02 18:08