queue_free() doesn't delete children. How to delete all nodes of a Scene?

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

Deleting children doesn’t work properly when called on a parent node. Is it a known bug? How can I delete all nodes of a scene properly?

How to reproduce:
two scenes: SceneA with a reference var other to other SceneB (append some children to SceneB root)

  • instance both SceneA and SceneB
  • set other to SceneB instance
  • call queue_free() on SceneB instance
  • check var other, it’s not null but it’s not a root of a SceneB, it holds some of the children (this happens sometimes)

I tried to use weak_ref but same thing since there is some reference to children nodes.

To clarify, queue_free() doesn’t free nodes immediately, it does that at the end of the frame, so it’s normal if other still holds a SceneB right after.

I tried your reproduction steps in Godot 3.1, but all I got after a few frames was a debugger error saying access to 'previously freed instance', so all things run correctly here.

Do you have an example project which reproduces this bug?

Zylann | 2019-04-17 18:03

yeah, I know that it’s only queued for detetion. I call it not immediately, after some time (I do tower defence game, where tower shoots, then cooldown of 2 seconds, then I check if target is null or not)
I need a sec to upload my project to github

luckyNyaNya | 2019-04-17 18:11

project

make collision shapes visible in the project.
Now I don’t get any error (using weak_ref trick), dammit. Look at Planet.gd , method shoot(), so what I try to achive is when a creep dies, the planet script looks for new target . Is there a better way to check for null instance?

luckyNyaNya | 2019-04-17 18:49

if target == null:
	target = creeps[0]
else:
	var wr = weakref(target)

There is a problem with how you expect weakref to work: it works with ref-counted types, however nodes are not such thing (they don’t inherit Reference. In your use case, you should better use is_instance_valid.
Weak references are instead used to have the ability to access a ref-counted object, but without owning a reference to it. For example, if a resource is referenced in two places, it won’t get freed until the two places stop referencing it (set to null). But, if one is using a weakref, then just setting the other to null will suffice, and the weakref will turn “invalid” automatically. But again, that doesn’t apply to nodes.

Now I test your project without the weakref and it also does Invalid get index 'name' (on base: 'previously freed instance')..
If I write if not is_instance_valid(target): print("erased"), it correctly prints that the object is erased. Well, can’t reproduce here on Windows 10.

Zylann | 2019-04-17 20:37