I am making a tool script that uses child_exiting_tree signals. As I remove children one by one, triggering that signal works just fine. But I also have thousands of children, so when I close the scene in the editor, it hangs for a few seconds, because it is calling child_exiting_tree signal thousands of times (unnecessarily at this point). It hangs even if I put in a check that catches this case (it appears to be the signal triggering itself that causes the hang, not the function the signal calls). I was going to disconnect the signal when my tool node is freed, but before its children leave the tree (using NOTIFICATION_PREDELETE) but I ran into some problems. The order of NOTIFICATION_PREDELETE and _on_child_exiting_tree appears to be different when run as a tool script. In attempting to debug, I boiled it down to this test:
When running the game, if I call queue_free() on my tool node, the order of printing is
NOTIFICATION_PREDELETE before child_exiting_tree
But when the same code executes in the editor the order appears to be reversed:
first child_exiting_tree, then NOTIFICATION_PREDELETE (in fact, in this case, NOTIFICATION_PREDELETE doesn’t print until after exited_tree!)
And finally, if I delete the tool node using the scene tree editor in the Godot GUI , the NOTIFICATION_PREDELETE doesn’t fire at all.
Reading the docs, NOTIFICATION_PREDELETE is called as a destructor. Which means it is only called when the node is destroyed.
Here you are deleting the node, so it knows its getting deleted, and then has to tell all its children.
No idea why its different in the editor, but it may have to do with the fact that the node is visible in the editor’s scene tree, and so the destructor just has a race condition that’s happening that never appears when running the game because there’s no scene tree it needs to delete from. (This is a guess.)
Really weird. Might be a bug, and might be worth logging as a bug.
Perhaps someone will have a better answer, but based on what you’re seeing, that’s the way it works, so it might be better to try a different approach.
Gotcha. Since the node gets destroyed at different times in those different cases, a different approach would be best. Anyone have a suggestion? It looks like, when the tool node leaves the scene tree, that is when I want to disconnect the child_exiting_tree signal. However, I am not aware of any signal or notification I can use to do that, since as far as I can tell, exit_tree(), exiting_tree and exited_tree all occur after child_exiting_tree gets called during a queue_free operation. If anyone can see another approach, or something I’m missing here, please let me know.