Thanks.
Creation and destruction of players in my game is already very fast, since models are loaded once at startup and afterwards players are created by cloning existing scenes. So performance-wise this part is not an issue for me.
In my case, Player is not only a visual object. It also owns networking ,database, logic, and background threads. Because of that, separating game logic (TPlayer as TComponent) from rendering (TCastleScene / behaviors) felt more natural for me.
At this stage of the project, the game has grown quite a lot, so changing the base design now is not really possible. Based on my understanding so far, I believe the general direction is correct,
and the main thing I need to improve is handling lifetime and ownership between logic components and visual objects in a safer way.
The “false exceptions” I observed were related to TExposedTransform instances.
In CGE, TCastleTransform used by TExposedTransform is created like this:
{ Create new TCastleTransform.
Note
- We connect to it only by Name, not any other internal reference.
This is important, as we need to restore the connection
e.g. after deserializing it from design file.
- We use current Owner as the owner, not Self.
This makes it work in case of editor or TransformLoad nicely.
Intuitively, we don't want to manage the lifetime of these scenes
here: the lifetime of them should be up to our owner.
}
TransformChild := TCastleTransform.Create(Owner);
TransformChild.Name := TransformNamePascal;
Add(TransformChild);
Because TExposedTransform is freed automatically when its owner (TPlayer)
is destroyed, the previous implementation of ChildFreeNotification that tried
to free or remove it was unnecessary. In my case, I now clear all exposed
transforms manually in TPlayer before destruction (ClearPlayerExposedTransforms).
which avoids executing:
procedure TCastleSceneCore.TExposedTransform.ChildFreeNotification(const Sender: TFreeNotificationObserver);
begin
// free this TExposedTransform instance, removing it from FExposeTransforms
// ParentScene.FExposedTransforms.Remove(Self);
end;
Actually, there is really no need to call ClearPlayerExposedTransforms.
TExposedTransform is freed automatically when its owner (TPlayer) is destroyed.
When running the game and pressing F8, the CGE debug overlay shows
TExposedTransform objects as “existing.”
However, this does not mean they are actually alive in memory — all references
in the viewport are already removed, as confirmed by Viewport.Items.Count,
which is always correct.
If I manually execute ClearPlayerExposedTransforms, then these objects immediately
disappear from the debug overlay. “F8”
I may make a video to demonstrate this.
The important thing now: 0 exceptions
