I have 2 tcastlescenes. I add scene2 to scene1. If I then call scene1.clear, should it free scene2? scene1 is the owner of scene2. I was under the impression scene2 would be freed when scene1 is cleared, but it appears to not be the case?! Am I missing something?
Indeed, it’s a trap. When you call TCastleSomething.Clear
you remove children. However, you don’t Free
the children.
What happens under the hood:
Let’s imagine you do Scene1 := TCastleScene.Create(FreeAtStop)
. Note that FreeAtStop
thing - it’s “owner” of the scene, or in other words - object that will Free
this scene if it gets freed itself. When the TCastleView
calls Stop
it will also call FreeAtStop.Free
which in turn will free the Scene1
.
Now you create Scene2 := TCastleScene.Create(Scene1); Scene1.AddChildren(Scene2);
. This time Scene2
is “owned” by Scene1
. So when Scene1
calls Free
the Scene2
will also free. However, this will not happen when you call Scene1.Clear
. It only removes Scene2
from the active children, but doesn’t free it.
So, if you want to remove AND free Scene2
you’ll need to first remove and then free it, like this:
Scene1.Remove(Scene2); // or Scene1.Clear;
FreeAndNil(Scene2);
UPDATE: In my game I have adding/removing UI buttons very often. And to avoid accumulating memory too much, I’ve made a special method ClearAndFree
which does very similar to the above, just calls Remove
and then Free
on all children sequentially.
Actually you can just do FreeAndNil(Scene2)
. There’s no need to remove Scene2
from parents – no need for Scene1.Remove(Scene2)
, and no need for Scene1.Clear
(unless Scene1
may have other children you also want to remove). Scene2
will be removed from parents automatically when it is freed, we make it automatically to avoid having ever dangling pointers in the hierarchy.
The general way of thinking about this is, that I find useful: the ownership is independent from parent-child relationship. This is true in CGE components, just like in e.g. VCL or LCL or FMX components.
-
Ownership says that owner automatically frees the owned components, when the owner gets destroyed.
-
Parent-child dictate what is visible underneath what, and the coordinate system (children are specified in coordinate system of the parent).
Having these 2 systems independent is very useful – you often want to free things at different times when they are removed from parents.
The TCastleTransform.Clear
only deals with parent-child relationship, and never frees anything.
See also Castle Game Engine Overview For Unity Developers | Castle Game Engine - " What is the difference between Owner
and Parent
in CGE?".
P.S. That being said, I recognize that “Clear” name may be confusing here, so let me at least make it a “documented trap” Added API docs:
(These are committed to a delphi-linux branch now, but shall very soon be merged to master )
Thanks for the clarifications!