Pooling in gameplay code is a concept, so it depends on what you want to pool, so there is no "best" way in general, but it's often common sense on a per case basis:
Pooling sprites or meshes requires to just hide them.
Pooling physics objects requires to remove them from all layers they are into.
Pooling sample players requires to stop all their sounds.
Pooling AnimationPlayers requires to stop their animation.
Pooling a scene instance which contains all of the above requires to take care of all of them, unless your gameplay decisions allows you to take some shortcuts.
Pooled nodes can stay in the tree, unless it's inconvenient for you, in which case you can indeed remove them from the tree (which also takes care of much special cases listed above, though it might be a bit slower).
However, if you do so (and even in other methods), you should have a list per type of object in which you put the "unused" objects, otherwise they will leak.
About removing nodes from tree: in the question you linked, I was removing a node from within a signal handler, which doesn't seem to be allowed currently. The solution is to use call_deferred
to postpone the removal to the end of the frame.
In Godot 3, _ready
is not called again when nodes get re-added to the tree: https://github.com/godotengine/godot/issues/17182
So you must think about pooling a little bit when you design your scenes.
Don't do too much fluff for pooling either, because that could defeat the purpose, and there is no efficient way of doing "general" pooling (which would end up being what the Godot internals do in the first place, which you want to avoid with your own pooling!).
Instancing an object from the pool again requires a custom spawning logic. It can range from calling show
to having your own on_spawn
function in which you do everything needed.
Another catch is that if you want to also preallocate objects to not have a first-creation stutter, you should not assume that _ready
or _enter_tree
means the object spawns, because depending on your pooling strategy they could get called when you preallocate them. Being "pooled" is like a "dead" state, it has to be taken into account in your logic.
And importantly, profile your game to see if pooling improves things, because there is no point doing that otherwise. Also, remember there are other ways to optimize things, like not using nodes in the first place and use servers directly.