MyScene.Url := 'castle-data:/my_model.gltf';
MyScene.Translation := Vector3(1, 2, 3);
MyScene.PlayAnimation('run', true);
GameObject
?Assets
subdirectory?Time.timeScale
?Time.deltaTime
?Owner
and Parent
in CGE?If you come with a knowledge of another game engine, like Unity, this page will try to explain how some concepts map to Castle Game Engine. If you have any questions, remember to ask on forum, Discord chat or other places.
GameObject
?GameObject
in Unity is (simplifying) something that exists in your world, and may be visible, and may have children that are affected by a transformation.
For game objects (not user-interface), the closest equivalent of GameObject
in Castle Game Engine is the TCastleTransform
class. Instances of TCastleTransform
can be arranged in a hierarchy, where each element transforms (moves, rotates, scales) the children. The most important class of CGE is the TCastleScene
, which is a descendant of TCastleTransform
that can actually render/animate/collide a model. Simply set TCastleScene.Url
to load your model (like a glTF file) there.
Our manual documents TCastleScene
and TCastleTransform
features in chapter Viewport with scenes, camera, navigation. Basically you can do stuff like
MyScene.Url := 'castle-data:/my_model.gltf';
MyScene.Translation := Vector3(1, 2, 3);
MyScene.PlayAnimation('run', true);
The TCastleTransform
hierarchy is placed in a TCastleViewport
, which is a 2D user-interface element (descendant of TCastleUserInterface
).
For objects that are user-interface elements, the most important base class is TCastleUserInterface
. It has many descendants, like
obvious user interface controls: TCastleButton
, TCastleLabel
, TCastleRectangleControl
, TCastleImageControl
…
layouts: TCastleVerticalGroup
, TCastleHorizontalGroup
,
and finally a critical UI component TCastleViewport
which is a "gateway" to actually render a hierarchy of TCastleTransform
.
See user interface documentation.
In the simplest case, for each 3D model, you create a TCastleScene
instance. You can do this visually, using the CGE editor, or from code.
To group (and transform as a group) a number of TCastleScene
instances you can use additional TCastleTransform
instances. The TCastleScene
is also a TCastleTransform
descendant, so it can have children too.
Follow the template "3D FPS Game" (create it by running our editor, choose "New Project" and then choose "3D FPS Game" as a starting point). In the resulting project, open the design data/gameviewplay.castle-user-interface
in the editor, to actually see what I mean (in this and previous answer).
Our goal with CGE editor is to provide an experience similar to Unity and other game engine editors. So you can drop 3D models on your design, and drag them to design a level.
Short answer:
The equivalent of MonoBehaviour
is TCastleBehavior
class documented at behaviors. You can attach it to TCastleTransform
to control it.
Full answer:
There are multiple ways how you can control CGE stuff from code:
Define a class descending from TCastleBehavior
(see behaviors), and add an instance of it to TCastleTransform
. Like
type
TMyBehaviorClass = class(TCastleBehavior)
public
procedure Update(const SecondsPassed: Single; var RemoveMe: TRemoveType); override;
end;
Then add such behavior instance from code:
var
MyBehavior: TMyBehaviorClass;
begin
MyBehavior := TMyBehaviorClass.Create(SomOwner);
MyBehavior.Xxx := ...; // configure necessary parameters
MyTransform.AddBehavior(MyBehavior);
end;
See our template "3D FPS Game" (create it by running our editor, choose "New Project" and then choose "3D FPS Game" as a starting point) that shows exactly this approach. It defines a trivial TEnemy
class that defines the logic of an enemy, and is a TCastleBehavior
descendant. It controls the enemy movement. It also allows to check (e.g. when shooting ray) "did I hit an enemy" by checking SomeTransform.FindBehavior(TEnemy) <> nil
.
While the above examples show attaching a behavior using code, you could also add TEnemy
in editor. See editor and custom components docs for information how to register TEnemy
class in editor. This requires to restart editor within the project with menu option "Project -> Restart Editor (With Custom Components)". It is an extra step, but it makes sense for complicated behaviors, which can be configured in the editor easier.
The engine comes with a few standard behaviors too (like TCastleBillboard
, TCastleSoundSource
) and these are comfortable to add and configure from the editor.
You can control things from the view (see views). The view like TViewPlay
(see above mentioned template "3D FPS Game") has its own methods to Update
and handle input. The view can keep references to everything you have in your world, and it can control them.
For example you can process all the creatures in the view method like TViewPlay.Update
. Our manual about controlling viewport using code shows example of it, to move multiple cars.
You can also assign events, like OnClick
. Most UI controls expose obvious events, like TCastleButton.OnClick
. You are free to handle these events at one central place (like an LCL TForm
descendant (only if you use TCastleControl
), or CGE TCastleView
descendant) or decentralized (e.g. create a different instance of your own class to handle events of each different creature, different item).
The approach to use events is similar to using UI in Lazarus LCL or Delphi VCL.
This approach is best when you want to handle in one class (the view) all events related to some UI, for example clicks on all buttons visible in game options.
Another way to control things in CGE is to create class descendants from existing classes. In CGE you can create descendants from almost all classes (including important TCastleTransform
and TCastleUserInterface
), and override virtual methods there. E.g. you can override TCastleTransform.Update
to perform something every frame.
So you could define a class like TMyCreature
that descends from TCastleTransform
or TCastleScene
. This class would control it’s own transformation (e.g. it would change it’s own Translation
to move the creature) and it would possibly load some children (more TCastleTransform
and TCastleScene
instances) to show and animate the creature.
This is a classic OOP approach. This is like Unreal Engine that allows you to define your own actor classes that override the base class.
Assets
subdirectory?You should place your game data in the data
subdirectory of the project. See manual about the "data" directory. It will be automatically packaged and available in your games.
Everything inside your data
subdirectory is loadable at runtime. In this sense, it is actually similar to Assets/Resources/
subdirectory of Unity, if you care about details.
Things that are not your game data (like your source code) should not be placed in the data
subdirectory. The source code should live outside of data. Only the compiler must be able to find it (you can specify your sources locations using standard Lazarus Project Options and/or (for building cross-platform projects) using <compiler_options>
in CastleEngineManifest.xml). By convention, most CGE examples place Pascal source code in the code
subdirectory (or in top-level project directory), but this is really only a convention.
The layout of a larger CGE project may be like this:
my_project/ <- the project root CastleEngineManifest.xml <- this manifest file is used by both CGE build tool and CGE editor data/ <- game data lives here; up to you how to organize this CastleSettings.xml <- defines UI scaling, default font example_image.png example_model.gltf gameviewmainmenu.castle-user-interface ... code/ <- Pascal game code lives here; up to you how to organize this gameinitialize.pas gameviewmainmenu.pas <- Pascal unit corresponding (by convention) to gameviewmainmenu.castle-user-interface ... ... <- any other subdirectories and files? Up to you. Consider docs/ and README.md.
See supported model formats. In short: glTF is the best :) This documentation page also links to instructions for various authoring tools "how to export your data".
Test your models with Castle Model Viewer to see what is supported. If you double-click on a model from editor, it will automatically launch Castle Model Viewer.
No, and we will probably never do (unless indirectly, through some universal conversion library or through automatic conversion using FBX2glTF). FBX is a proprietary model format by Autodesk. Please don’t use FBX, it’s proprietary (the Autodesk specification of FBX is "secret" deliberately, and Autodesk only sanctions using FBX through it’s paid SDK), and also not that good. Use glTF which is excellent.
If you have existing models in FBX format you can convert them to glTF (use Godot Engine fork of FBX2glTF). If you have the source versions of your models, possibly you can just reexport them from your authoring software to glTF. You can also use Blender or a number of other tools to convert between model formats.
More information: FBX model format.
A short summary of the answer: Use TCastleWindow
. If all you want is a cross-platform game, where everything is rendered using Castle Game Engine. If you come here and want to "just make a game using CGE", use TCastleWindow
.
Details: The difference is outlined on https://castle-engine.io/manual_lazarus_control.php :
TCastleControl
means that engine rendering is inside Lazarus form. That is, TCastleControl
is a regular Lazarus control that can be placed on a larger form. You can use Lazarus designer to place LCL controls, and you can use CGE editor to design CGE controls (within TCastleControl
).
TCastleWindow
means that engine rendering is a separate window, and we’re not using LCL. You can use CGE editor to design controls. So you lose access to LCL controls, but in exchange you get perfect cross-platform code (Android, iOS, Switch work only with TCastleWindow
).
In both cases, you can use Lazarus as an IDE — to write code, debug etc. In both cases, you can use CGE editor to design CGE controls (that go inside TCastleControl
or TCastleWindow
).
Time.timeScale
?An equivalent is to set MyViewport.Items.TimeScale
.
It is specific to the given world, which is an instance of TCastleAbstractRootTransform
available in MyViewport.Items
. Simple games will just have one viewport, a TCastleViewport
instance. Multiple instances of TCastleViewport
are possible, and then can share the same world, or show a different world (just assign Items
between).
There in an additional time scaling possible by TCastleScene.TimePlayingSpeed
. This is local in given TCastleScene
instance.
Time.deltaTime
?In Container.Fps.SecondsPassed
. See the view events for the most trivial usage example.
In you override the TCastleUserInterface.Update
(including TCastleView.Update
) or TCastleTransform.Update
method, then you also have an explicit parameter SecondsPassed
that contains this value. In TCastleTransform.Update
the time is already scaled (if you used MyViewport.Items.TimeScale
mentioned above).
Both TCastleTransform
and TCastleUserInterface
have a Boolean Exists
property: TCastleTransform.Exists
, TCastleUserInterface.Exists
. By default this is true
. Simply set it to false
to make everything behave as if this component was not part of the hierarchy. Non-existing components are not visible, do not collide, do not handle any input, do not cause any events etc. So Unity GameObject.SetActive(xxx)
translates to CGE MyTransform.Exists := xxx
.
You can also control the TCastleTransform.Collides
, TCastleTransform.Pickable
and TCastleTransform.Visible
properties of TCastleTransform
. These are useful to make something e.g. visible but non-collidable, or collidable but invisible. Note that when Exists
is false
, it "overrides" them, and non-existing object never collides and is never visible.
We have UI scaling, to adjust to any screen size smartly, and it works similar to Unity canvas scaling. It allows to design assuming a specific window size, and as long as you set sensible anchors, the design will look reasonable at various screen resolutions (even with different aspect ratio). It merely scales the coordinates — the actual rendering is done for the final resolution, so it looks "sharp" always.
The scaling is configured using CastleSettings.xml file. The default CGE editor "New Project" templates set UI scaling to adjust with a reference window size of 1600x900.
Mobile services like ads, analytics, in-app purchases and more are available as Android services or iOS services. You declare them in CastleEngineManifest.xml and then build the project using our build tool. These allow to integrate your code with various 3rd-party services (from Google, Apple and others) or use mobile APIs that require special permissions (like vibrations).
The "service" means "a part of the project, in binary or source code, added during the build stage".
Android services may contain Java code, precompiled libraries for Android, Gradle configuration and more.
iOS services may contain Objective-C code, precompiled libraries for iOS, CocoaPods configuration and more.
On other platforms, so far we didn’t need a similar concept. E.g. integration of CGE with 3rd-party services on desktops is always possible by normal Pascal units that expose e.g. FMOD or Steam API. That said, we plan to add "services" for all platforms at some point — to distribute anything that contains platform-specific files (like shared libraries) even easier.
You can of course replace or enhance the shaders used by our engine.
We have compositing shaders which is like Unity3d "surface shaders" but on steroids :) I’m quite proud of this, it really allows to easily write a piece of shader code and add it to some shapes, and (compared to Unity3d "surface shaders") it has some cool new features, like the ability to combine many effects (so you can write one shader effect, maybe add another shader effect), or changing shading of lights or textures or making procedurally generated (on GPU) textures.
See examples/viewport_and_scenes/shader_effects for simple demo in Pascal that attaches an effect, coded in GLSL, to a scene loaded from glTF. The shader uniform variable can be set at runtime from Pascal of course, and thus you can configure the shader at runtime with zero cost.
See https://github.com/castle-engine/demo-models, subdirectory compositing_shaders for demos of Effect
nodes in pure X3D (you can load them all from CGE; it’s just that these demos create Effect
node by X3D code, not by Pascal code).
The compositing shaders documentation, in particular this document, describe how these shader effects work.
In Unity, your typical world is a hierarchy of 3D GameObject
s.
Somewhere in this world, you have a Camera
component, that determines the camera parameters (like projection) and viewport sizes. The transformation of the associated GameObject
determines the camera position and rotation.
You can have multiple Camera
components on different GameObjects to have multiple viewports.
Somewhere in this world, you have a canvas that acts as a place for 2D controls like buttons and images.
In CGE, it is a bit different. Viewport (TCastleViewport
) is a 2D control, and it can render 3D world inside. This means:
You design a hierarchy of TCastleUserInterface
components. They all share the same properties to control position and size, using anchors, using TCastleUserInterface.FullSize
(fill the parent) etc.
There are numerous TCastleUserInterface
descendants, like buttons, images, and viewports. So TCastleViewport
is just a descendant of TCastleUserInterface
, arranged just like any other UI control.
Within a viewport (TCastleViewport
) instance, you place your 3D or 2D world (in Viewport.Items
). TCastleViewport.Items
is a hierarchy of TCastleTransform
. These are 3D or 2D objects, rendered from the point of chosen camera.
A viewport always renders using a chosen camera in TCastleViewport.Camera
. This camera determines projection settings and position, rotation of the viewer. This camera determines which part of the world (your TCastleTransform
instances) is visible. There can be multiple TCastleCamera
instances in the world, but at a given time, the viewport renders using the one chosen camera. You can of course change which camera is "chosen" by just changing TCastleViewport.Camera
value at any time.
To have multiple viewports in Castle Game Engine you, intuitively, need to have multiple instances of TCastleViewport
. They each can occupy a different part of the screen. They can show a different 3D world or the same 3D world. See Multiple viewports to display one world.
The above describes the typical design as seen in editor templates. To see it in action, create a "New Project" in the editor, using the template like "3D FPS Game", and open the design data/gameviewplay.castle-user-interface
in the editor.
In short, in Unity "viewport" and "camera" and "UI" are just things inside your 3D world. In CGE, "viewport" (and the corresponding "camera") contains your 3D world, and "viewport" is part of your UI.
In effect,
In CGE the "viewport" can be positioned/sized just like any other 2D control. See examples/viewport_and_scenes/multiple_viewports for an example that shows 4 viewports.
The Z-order (what is in front/behind) of the viewport in CGE is straightforward, it works just like all other 2D controls. You can easily place other 2D controls in front or behind a viewport (the latter is useful if the viewport has Transparent
background).
In CGE each "viewport" may show a completely different, unrelated, 3D world. The viewports can also share the world (show the same world from different cameras), simply set them the same Viewport.Items
value.
Prefabs are a way to store GameObject hierarchy, with Unity components attached, in a file.
See reusable designs. This is the equivalent of Unity prefabs in Castle Game Engine.
The usual equivalent in CGE is to create a xxx.castle-transform
file where you create a design with a root being TCastleTransform
or TCastleScene
. This allows you to compose a transformation hierarchy of TCastleTransform
/ TCastleScene
instances. You can then load this xxx.castle-transform
multiple times, as a single thing. See the examples/advanced_editor, the file data/soldier_with_cape.castle-transform
there is a simplest example of this approach.
The equivalent of prefabs for Unity UI elements is a UI design file, xxx.castle-user-interface
, already mentioned above.
The equivalent of Unity AudioSource is our TCastleSoundSource
. It is a behavior, you attach it to a parent TCastleTransform
and it can play spatialized sound. Note that for non-spatial sounds, you can also just call TSoundEngine.Play
, this is simpler and there’s no need for a TCastleSoundSource
instances.
The equivalent of Unity AudioClip is our TCastleSound
.
See manual chapter about sound for information how to use sound in CGE.
Owner
and Parent
in CGE?Owner
comes from from the standard TComponent
. See Manual and automatic freeing (Pascal introduction). It manages memory (owner will free the owned instance, when the owner is freed before the owned).
Parent
is a visual parent. CGE UI has TCastleUserInterface.Parent
. CGE transformations have TCastleTransform.Parent
.
So Parent
and Owner
are separate concepts, even declared in different classes.
Sometimes both Parent
and Owner
may be set to the same instance, if it is suitable in the particular situation, but in general these 2 things just perform 2 separate functions. For example, in CGE editor, owner of everything in the design is always one central DesignOwner
component. When you load the design yourself, you provide the Owner
instance explicitly (as a parameter to UserInterfaceLoad
, TransformLoad
, ComponentLoad
) and then you specify parent yourself but adding the design to the hierarchy (e.g. MyParentUi.InsertFront(MyLoadedUi)
).
Use TCastleDownload
. Similarly to UnityWebRequest
, this class can send HTTP requests (GET, POST and others) and can download data asynchronously. It has been designed as an easy but also powerful way to communicate over the network. It also handles getting data from non-network requests (file://
and other protocols) so you can easily switch your URLs.
CGE examples/network demonstrate it.
This is how various physics forces methods (see physics) map from Unity to CGE:
https://docs.unity3d.com/ScriptReference/Rigidbody.AddForceAtPosition.html → TCastleRigidBody.AddForceAtPosition
(both take 2 params "Force, Position" in world coordinate space)
https://docs.unity3d.com/ScriptReference/Rigidbody.AddRelativeForce.html → TCastleRigidBody.AddForce
(both take 1 param "Force"). Pass ForceInLocalCoordinates
= true
.
https://docs.unity3d.com/ScriptReference/Rigidbody.AddForce.html → TCastleRigidBody.AddForce
(both take 1 param "Force"). Pass ForceInLocalCoordinates
= false
.
https://docs.unity3d.com/ScriptReference/Rigidbody.AddTorque.html → TCastleRigidBody.AddTorque
(both take 1 param, "Torque", in world coordinate space)
The above mapping applies to default Unity usage with ForceMode.Force
.
For impulses (using Unity API with ForceMode.Impulse
) we have a separate method TCastleRigidBody.ApplyImpulse
.
To improve this documentation just edit this page and create a pull request to cge-www repository.