# About TCastleTransform Remove from TCastleViewport

**URL:** <https://forum.castle-engine.io/t/about-tcastletransform-remove-from-tcastleviewport/2202>\
**Category:** Uncategorized\
**Created:** [August 26, 2026, 7:59am UTC](https://forum.castle-engine.io/t/about-tcastletransform-remove-from-tcastleviewport/2202 "2026-08-26T07:59:36Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![pascalboy](https://forum.castle-engine.io/letter_avatar_proxy/v4/letter/p/73ab20/32.png) [@pascalboy](https://forum.castle-engine.io/u/pascalboy)\
**Post date:** [August 26, 2026, 7:59am UTC](https://forum.castle-engine.io/t/about-tcastletransform-remove-from-tcastleviewport/2202/1 "2026-08-26T07:59:36Z")

</div>

when game over check Clear All TCastleTransform;

First : TCastleTransformend.Exists:= false;  
Secound : TCastleTransform.Update(const SecondsPassed: Single; var RemoveMe: TRemoveType); RemoveMe := rtRemove;

First = Second？

```auto
procedure TTowerManager.ClearAllTower;
var
  i : Integer;
  Tower : TTower;
begin
  for i:= FTowerList.Count - 1 downto 0 do
  begin
    Tower := FTowerList.Items[i];
    if Assigned(Tower) then
    begin
      if Tower.Exists then
      begin
        Tower.Exists := False; //need to TCastleViewport.Items.Remove(Tower) ?
      end;
      FreeAndNil(Tower);
    end;
  end;
end; 

```

---

<div class="post-metadata">

**Author:** ![phomm](https://forum.castle-engine.io/user_avatar/forum.castle-engine.io/phomm/32/2827_2.png) [@phomm](https://forum.castle-engine.io/u/phomm)\
**Post date:** [August 26, 2026, 4:07pm UTC](https://forum.castle-engine.io/t/about-tcastletransform-remove-from-tcastleviewport/2202/2 "2026-08-26T16:07:37Z")

</div>

What is TTower ? how do you create them? If you pass an owner to constructor Create (I assume TTower is descendant of TCastleTransform), then Owner will be responsible for their Freeing. If you create them manually and do not pass Owner, but instead store in some List (FTowerList) then you need manually control what you do.

Items object of viewport is not responsible for freeing, it is about being a parent to them and showing them inside a viewport.

---

<div class="post-metadata">

**Author:** ![pascalboy](https://forum.castle-engine.io/letter_avatar_proxy/v4/letter/p/73ab20/32.png) [@pascalboy](https://forum.castle-engine.io/u/pascalboy)\
**Post date:** [August 27, 2026, 3:18am UTC](https://forum.castle-engine.io/t/about-tcastletransform-remove-from-tcastleviewport/2202/3 "2026-08-27T03:18:06Z")

</div>

Thank you ! **I asked the wrong question!**

TTower = class(TCastleTransform)

TTower.Create;

TCastleViewport.Items.Add(TTower);

dosomething;

TTower.Exists : =false; TCastleViewport.Items.Remove(TTower); this is my **question!**

FreeAndNil(TTower);

---

<div class="post-metadata">

**Author:** ![phomm](https://forum.castle-engine.io/user_avatar/forum.castle-engine.io/phomm/32/2827_2.png) [@phomm](https://forum.castle-engine.io/u/phomm)\
**Post date:** [August 27, 2026, 12:28pm UTC](https://forum.castle-engine.io/t/about-tcastletransform-remove-from-tcastleviewport/2202/4 "2026-08-27T12:28:49Z")

</div>

I still don’t get what IS your question, you’re just showing the code.

But, Yes, you need to remove your object from Items before doing Free, you don’t even need to do Exists := false.

---

<div class="post-metadata">

**Author:** ![michalis](https://forum.castle-engine.io/user_avatar/forum.castle-engine.io/michalis/32/3_2.png) [@michalis](https://forum.castle-engine.io/u/michalis)\
**Post date:** [August 28, 2026, 12:38pm UTC](https://forum.castle-engine.io/t/about-tcastletransform-remove-from-tcastleviewport/2202/5 "2026-08-28T12:38:53Z")

</div>

Admittedly I’m also not clear about the question:) You’re posting pieces of code or pseudo-code, and they only show parts of the code, it is not clear where is the problem / where is the question 🙂

What are you actually trying to do? Provide more description what is your ultimate goal, so we don’t have [XY problem](https://xyproblem.info/) and we don’t guess 🙂 If something is not working for you? Provide a compete testcase where things fail to compile / work.

Some information:

1. Setting `Exists` to `false` means that the component remains in the tree (e.g. in `Viewport.Items`, if that’s where it was added), but behaves as if it wasn’t there. So it will not be rendered (visible), will not collide etc., but is still on `Viewport.Items`, so it’s easy to make it active again.
2. Removing from `Viewport.Items` means that the component is not part of the viewport anymore (and setting `Exists` to `false` is not necessary in this case). So it will not be rendered (visible), will not collide etc.
3. Independently of above, you need to free the component at some time. Freeing it → makes AD 1 and AD 2 unnecessary, freed component is automatically removed from the viewport .

---

<div class="post-metadata">

**Author:** ![pascalboy](https://forum.castle-engine.io/letter_avatar_proxy/v4/letter/p/73ab20/32.png) [@pascalboy](https://forum.castle-engine.io/u/pascalboy)\
**Post date:** [August 28, 2026, 3:36pm UTC](https://forum.castle-engine.io/t/about-tcastletransform-remove-from-tcastleviewport/2202/6 "2026-08-28T15:36:38Z")

</div>

> [@pascalboy](#):
>
> ```delphi
> // examples\sprite_sheets\sprite_sheets_demo\code\gameviewmain.pas
> unit GameViewMain;
> {$mode ObjFPC}{$H+}
> 
> interface
> 
> uses Classes,
> CastleComponentSerialize, CastleUIControls, CastleControls,
> CastleKeysMouse, CastleTransform, CastleScene, CastleViewport, castlevectors, CastleMessages, CastleWindow, CastleSceneCore, x3dnodes;
> 
> type
> TScene4 = class(TCastleTransform)
> private
> FNeedFree: Boolean;
> FScene: TCastleScene;
> FViewport: TCastleViewport;
> procedure OnScene4WalkStopped(const Scene: TCastleSceneCore;
> const Animation: TTimeSensorNode);
> public
> constructor Create(AOwner: TComponent); override;
> destructor Destroy; override;
> procedure PlayWalk(AViewport: TCastleViewport; AVector3 : TVector3);
> procedure Update(const SecondsPassed: Single; var RemoveMe: TRemoveType); override;
> end;
> 
> type
> { Main view, where most of the application logic takes place. }
> 
> { TViewMain }
> 
> TViewMain = class(TCastleView)
> private
> Scene3 : TCastleScene;
> Scene4 : TScene4;
> procedure CreateHumanA;
> procedure CreateHuman;
> procedure FreeHuman;
> procedure QueryScene3;
> procedure OnWalkStopped(const Scene: TCastleSceneCore; const Animation: TTimeSensorNode);
> published
> { Components designed using CGE editor.
> These fields will be automatically initialized at Start. }
> LabelFps: TCastleLabel;
> Viewport1: TCastleViewport; //add
> public
> constructor Create(AOwner: TComponent); override;
> procedure Start; override;
> procedure Update(const SecondsPassed: Single; var HandleInput: Boolean); override;
> function Press(const Event: TInputPressRelease): Boolean; override;
> end;
> 
> var
> ViewMain: TViewMain;
> 
> implementation
> 
> uses SysUtils;
> 
> constructor TScene4.Create(AOwner: TComponent);
> begin
> inherited Create(AOwner);
> FScene := TCastleScene.Create(Self);
> FScene.Url:= 'castle-data:/hero_animation/hero_high_fps.castle-sprite-sheet';
> Self.Add(FScene);
> FNeedFree := False;
> FViewport := nil;
> end;
> 
> procedure TScene4.OnScene4WalkStopped(const Scene: TCastleSceneCore; const Animation: TTimeSensorNode);
> begin
> Self.Exists:= False;
> FScene.Exists:= False;
> FNeedFree := True;
> end;
> 
> procedure TScene4.PlayWalk(AViewport: TCastleViewport; AVector3 : TVector3);
> var
> Params: TPlayAnimationParameters;
> begin
> FViewport := AViewport;
> 
> FScene.Exists:= True;
> Self.Exists:= True;
> 
> Self.Translation := AVector3;
> FViewport.Items.Add(Self);
> 
> Params := TPlayAnimationParameters.Create;
> try
> Params.Name := 'walk';
> Params.Loop := False;
> Params.Forward := True;
> Params.StopNotification := {$ifdef FPC}@{$endif}OnScene4WalkStopped;
> FScene.PlayAnimation(Params);
> finally
> Params.Free;
> end;
> end;
> 
> procedure TScene4.Update(const SecondsPassed: Single; var RemoveMe: TRemoveType);
> begin
> inherited Update(SecondsPassed, RemoveMe);
> if FNeedFree then
> begin
> Self.Free;
> end;
> end;
> 
> destructor TScene4.Destroy;
> begin
> inherited;
> end;
> 
> { TViewMain ----------------------------------------------------------------- }
> 
> constructor TViewMain.Create(AOwner: TComponent);
> begin
> inherited;
> DesignUrl := 'castle-data:/gameviewmain.castle-user-interface';
> end;
> 
> procedure TViewMain.Start;
> begin
> inherited;
> end;
> 
> procedure TViewMain.Update(const SecondsPassed: Single; var HandleInput: Boolean);
> begin
> inherited;
> { This virtual method is executed every frame (many times per second). }
> LabelFps.Caption := 'Viewport1.Items.Count=' + IntToStr(Viewport1.Items.Count) + ',FPS: ' + Container.Fps.ToString;
> end;
> 
> procedure TViewMain.OnWalkStopped(const Scene: TCastleSceneCore; const Animation: TTimeSensorNode);
> begin
> //FreeHuman; // !!!! [this is my question]
> Scene3.Exists:= False;
> end;
> 
> procedure TViewMain.CreateHumanA;
> begin
> Scene4 := TScene4.Create(Nil);
> Scene4.PlayWalk(Viewport1, Vector3(0,200,30));
> end;
> 
> procedure TViewMain.CreateHuman;
> var
> Params: TPlayAnimationParameters;
> begin
> if Assigned(Scene3) then Exit;
> Scene3 := TCastleScene.Create(Nil);
> Scene3.Url:= 'castle-data:/hero_animation/hero_high_fps.castle-sprite-sheet';
> //Scene3.PlayAnimation('Walk',True);
> Params := TPlayAnimationParameters.Create;
> try
> Params.Name := 'walk';
> Params.Loop := False;
> Params.Forward := True;
> Params.StopNotification := {$ifdef FPC}@{$endif} OnWalkStopped;
> Scene3.PlayAnimation(Params);
> finally
> Params.Free;
> end;
> Viewport1.Items.Add(Scene3);
> Scene3.Translation := Vector3(0,200,30);
> end;
> 
> procedure TViewMain.FreeHuman;
> begin
> //Viewport1.Items.Remove(Scene3);
> //Scene3.Exists:= False;
> if Assigned(Scene3) then FreeAndNil(Scene3);
> end;
> 
> procedure TViewMain.QueryScene3;
> begin
> if Assigned(Scene3) then
> MessageOK(Application.MainWindow, 'Scene3 is Create')
> else
> MessageOK(Application.MainWindow, 'Scene3 is nil');
> end;
> 
> function TViewMain.Press(const Event: TInputPressRelease): Boolean;
> begin
> Result := inherited;
> if Result then Exit; // allow the ancestor to handle keys
> 
> if Event.IsKey(keyC) then
> begin
> CreateHuman;
> Exit(true); // key was handled
> end;
> if Event.IsKey(keyF) then
> begin
> FreeHuman;
> Exit(true); // key was handled
> end;
> if Event.IsKey(keyQ) then
> begin
> QueryScene3;
> Exit(true); // key was handled
> end;
> if Event.IsKey(keyA) then
> begin
> CreateHumanA;
> Exit(true); // key was handled
> end;
> end;
> 
> end.             
> 
> ```

Thank you! I Fix It.

---

<div class="post-metadata">

**Author:** ![michalis](https://forum.castle-engine.io/user_avatar/forum.castle-engine.io/michalis/32/3_2.png) [@michalis](https://forum.castle-engine.io/u/michalis)\
**Post date:** [August 29, 2026, 5:49pm UTC](https://forum.castle-engine.io/t/about-tcastletransform-remove-from-tcastleviewport/2202/7 "2026-08-29T17:49:00Z")

</div>

Note: I didn’t review your code completely, but I understand your question is fixed. Cool!

Some notes from scanning your code:

1. Doing `Self.Exists:= False`, `FScene.Exists:= False` before `FNeedFree := True;` seems unnecessary. If you will soon free this instance (which also frees `FScene`), then it doesn’t matter what will be their `Exists` value. (unless they get rendered for 1 frame with invalid state?)

2. This looks dangerous:

> [@pascalboy](#):
>
> ```auto
> procedure TScene4.Update(const SecondsPassed: Single; var RemoveMe: TRemoveType);
> begin
> inherited Update(SecondsPassed, RemoveMe);
> if FNeedFree then
> begin
> Self.Free;
> end;
> end;
> 
> ```

This looks wriong – you are freeing the instance of `Self`, but this `Update` is running inside a loop that iterates over components, and your component is part of that list. This is a problem – by freeing yourself, you decrease the loop count, and undefined things (crashes, missing calls to other updates) may happen.

The `RemoveMe` parameter was introduced to `Update` as one way to avoid this mistake. Instead of `Self.Free`, do `Remove := rtRemove`. I realize that you maybe had some issues with this (judging from your first post in this thread), then we have to explore then and fix – simply doing `Self.Free` is really dangerous, even if it seems to work. See [TCastleTransform.Update docs](https://castle-engine.io/apidoc/html/CastleTransform.TCastleTransform.html#Update-Single-TRemoveType-).

An even simpler solution is to use [TCastleTransform.RemoveDelayed (with FreeInstance=true)](https://castle-engine.io/apidoc/html/CastleTransform.TCastleTransform.html#RemoveDelayed-TCastleTransform-Boolean-) or [ApplicationProperties.FreeDelayed](https://castle-engine.io/apidoc/html/CastleApplicationProperties.TCastleApplicationProperties.html#FreeDelayed-TComponent-).

My recommendation:

- remove `FNeedFree` field and tracking
- remove `TScene4.Update` method
- make `TScene4.OnScene4WalkStopped` just call `ApplicationProperties.FreeDelayed(Self)`, nothing more.
