Physics allows you to define rigid bodies that can
collide with each other (following the designated collider geometry)
are affected by forces (like gravity and custom forces you apply)
are connected by joints.
The physics collisions automatically result in a proper response, i.e. objects "bounce off" each other when they collide.
To achieve all this, Castle Game Engine is integrated with Kraft Physics Engine made by Benjamin 'BeRo' Rosseaux. Read on to learn how to add physics to your own games.
Use these components (available in both editor and code) to control the physics.
TCastleRigidBody
: This component activates processing the transformation by physics.
Colliders are components descending from abstract TCastleCollider
:
TCastlePlaneCollider
(using this collider forces the body to be static)
TCastleMeshCollider
(using this collider forces the body to be static)
A mesh that collides (referenced by TCastleMeshCollider.Mesh
) can be TCastleScene
, TCastleTerrain
, or any primitive descending from TCastleAbstractPrimitive
.
To make any TCastleTransform
affected by physics add there a collider (any TCastleCollider
descendant) and a rigid body (TCastleRigidBody
).
In the editor, adding any collider automatically also adds the TCastleRigidBody
, so you only need to do one step: add a collider. The usual way to do this is by right-clicking on a TCastleTransform
instance in your hierarchy, and choosing from context menu "Add Behavior → Physics → Collider → …".
Note
|
Adding a collider from 2D group will automatically also add TCastleRigidBody configured in an optimal way for 2D (using TCastleRigidBody.Setup2D ).
|
Then run "Physics → Play Simulation" (use the menu item or button on the header) and observe that body is affected by
gravity
collisions with other objects.
Note that various components descend from TCastleTransform
and thus can act as physics bodies: TCastleScene
, primitives like TCastleBox
, TCastleSphere
, even terrains TCastleTerrain
.
There are lots of options to tweak how things behave. See API docs for documentation.
You can visualize physics colliders (esp. useful if you disable the TCastleCollider.AutoSize
on them and want to see the effect) using the menu item "Physics → Show Colliders".
The colliders in general should not collide at start. You should set up the colliders to avoid it. To make the collider smaller than automatically calculated you can:
disable the TCastleCollider.AutoSize
and setup all collider sizes manually,
or set TCastleCollider.SizeScale
to value like 0.9
, to make the size (auto-detected or not) smaller by 90%.
Note
|
A good test to enjoy the physics is to make a "bullet" that will hit some rigid body with significant speed, so that you can see how it behaves on collision. To make a bullet, just
See quick demo movie. |
As with all CGE components, while you can add them by clicking in CGE editor (at design-time), you can also add them using Pascal code at run-time. Like this:
var
NewBody: TCastleRigidBody;
NewCollider: TCastleSphereCollider;
begin;
NewBody := TCastleRigidBody.Create(FreeAtStop);
//NewBody.Setup2D;
MyTransform.AddBehavior(NewBody);
NewCollider := TCastleSphereCollider.Create(FreeAtStop);
NewCollider.Restitution := 0.6;
NewCollider.Mass := 1;
MyTransform.AddBehavior(NewCollider);
end;
You can start a "Physics Simulation" right in the editor. This is a great way to test how physics behaves without the need to actually run the game.
During the simulation you can click around and modify the design even while the physics is runnning. Beware: the design will be restored to the original state when physics stops. If you want to really modify the design (not only make a temporary experiment), you should first stop the physics simulation.
Note
|
In the editor we only run the physics simulation, not your final game code. That said, various components may adapt to the "simulation" to behave in editor just as they do at run-time. Your custom components can adapt to simulation too, just honor the current CastleApplicationMode value.
|
The whole physics can work for 2D games as well as 3D. For 2D, remember to:
Adjust TCastleRigidBody
by locking rotation/translation (such that the object stays within the same XY plane). It’s easiest to do this by calling TCastleRigidBody.Setup2D
from code.
In CGE editor, just add "Physics → Rigid Body (2D)" component. Actually it will be added automatically if you add "Physics → Collider 2D → …".
Set TCastleCollider.Mode2D
to true
(to auto-size and to account for scale in a way better for 2D). In CGE editor, just add the "Physics → Collider 2D → …" components.
We feature a number of 2D physics demos in our examples on examples/physics, check them out.
You can apply forces from code. This can be used to simulate forces other than gravity. For example: wind or explosion.
See demos:
examples/physics/physics_forces - test various methods to apply forces.
examples/physics/physics_explosion - test explosion.
To apply the force use on of these methods:
TCastleRigidBody.AddForceAtPosition
- push objects in the given direction, with given strength, from the given position.
TCastleRigidBody.AddForce
- push objects in the given direction, with given strength. The direction may be in local or global coordinate system.
TCastleRigidBody.AddTorque
- rotate the objects using physics.
TCastleRigidBody.ApplyImpulse
- apply an instant impulse. This is more instant way of affecting the velocity than the AddXxx
methods above.
Here’s how an explosion can look like:
Instead of using forces, you can also just change the position/rotation of the object affected by physics, e.g. by directly changing TCastleTransform.Translation
.
Whether this is a good idea, depends on the object type:
Dynamic objects: If the object has TCastleRigidBody.Dynamic
= true
(TCastleRigidBody.Animated
is ignored in this case), it means physics simulation moves and rotates this object.
We allow you to change the object, e.g. by explicitly changing TCastleTransform.Translation
, but you should refrain from doing it often. As you effectively override physics calculations, forcing the physics engine also to reposition your object in various internal structures.
Kinematic objects: If the object has TCastleRigidBody.Dynamic
= false
and TCastleRigidBody.Animated
= true
, you are welcome to transform this object. Physics engine is prepared for it.
Static objects: If the object has TCastleRigidBody.Dynamic
= false
and TCastleRigidBody.Animated
= false
, you can change the object transformation, but you should refrain from doing so.
Physics engine may optimize static objects. You make this optimization counter-productive (the physics engine will have to reposition your object in various internal structures) if you change the transformation of static object often.
Use the TCastleAbstractRootTransform.PhysicsRayCast
to cast a ray and see whether it hits something. It takes and returns values (ray origin, direction, returned distance, point) in the world coordinate system.
Alternatively use the TCastleRigidBody.PhysicsRayCast
which is similar, but takes parameters in the coordinate system of the parent TCastleTransform
.
You can detect whether a collision has occurred by
Assigning a callback to events TCastleRigidBody.OnCollisionEnter
, TCastleRigidBody.OnCollisionStay
, TCastleRigidBody.OnCollisionExit
.
Or checking (e.g. in each view Update event) the value of TCastleRigidBody.GetCollidingTransforms
.
See the examples/physics/physics_2d_collisions for a demo.
Joints allow to connect one physics body to another in some way that limits their ability to move/rotate relative to each other.
For example a hinge joint forces one physics body to only be rotated relative to another along a given axis. Like a door that is attached to a wall using hinges and can only rotate in a constrained way.
Hitting a physics body with something (like another physics body or using the forces API) will respect the joints.
Joints can be made breakable which means they can be broken if sufficiently big force is used.
Joints are simply components in Pascal that are derived from TCastleBehavior
and can be attached to any TCastleTransform
.
You can add them from CGE editor using the "Add Behavior → Physics → Joints → …" menu item.
Each joint component has a number of properties to control its behavior.
Often joints have some anchors that can be manipulated visually if you right-click on the joint component in the hierarchy and do "Show Joint Tools".
Note
|
Joints only make sense for TCastleTransform that are affected by physics. So you most often need add TCastleRigidBody and some TCastleCollider descendant to the same TCastleTransform that has a joint.
|
Here’s a demo:
By default, all physics bodies are on the same, default layer (with index 0) and can collide with each other.
You can place bodies on different layers, like "ground", "enemies", "bullets" and so on. You can then configure which layer collides with which. You have 20 layers available.
There are really just 2 things to configure:
At each rigid body, set the TCastleRigidBody.Layer
to indicate the layer on which the body is.
To help with this, you can add names and even longer descriptions to layers. Do this through Viewport.Items.PhysicsProperties.LayerNames
. In the usual workflow, just click to configure LayerNames
using "…" button in the editor. The names and descriptions are only for the developer, to better document the layer meaning.
Configure which layer collides with which using the checkboxes at Viewport.Items.PhysicsProperties.LayerCollisions
. You can set them from code, or click on "…" from CGE editor to configure them visually.
The simple usage example is in examples/physics/physics_3d_collisions_layers/. More involved example is in examples/platformer.
We have a lot of examples dedicated to physics in the examples/physics subdirectory. Go ahead and check them out!
Current physics engine integration is just a start. The plans are:
Make TCastleWalkNavigation
use physics to move (just like TCastleThirdPersonNavigation
already can).
In progress already (by Andrzej KilijaĆski) - PR 533
(See section below about "Old system") Currently we also have an older, simpler, internal physics/collision engine in CGE, that takes care of some tasks: the collisions of player and creatures (from CastleCreatures), a simple gravity for them, and custom collision methods for you (like RayCollision, SphereCollision etc. in CastleTransform unit). The new physics engine should eventually replace them all, and there should be a flag to make it possible, and eventually it should even become the default, and the old collision implementation should be simply removed.
A shape within the TCastleScene
should be able to act like a rigid body, independent of the rest of the scene. Our current preferred plan to this is to depend that you will assign rigid bodies and colliders in CGE editor (or by Pascal code) to TCastleTransform
created by the ExposeTransforms
feature. And we can just synchronize changes from bones exposed by ExposeTransforms
back to the original model.
This will allow you to attach physics to particular parts (any transformation) of the model.
We are close to realizing this goal, except that ExposeTransforms
do not (yet) synchronize back their changes to the parent model.
Integration with other physics engines, through a layer providing a common API.
We consider these 2 candidates for proving an (alternative) physics engine now:
Bullet. Very full-featured, e.g. there’s soft body, not only rigid body.
Full integration with Bullet will require proper translation of Bullet API to C and then to Pascal (as Bullet is in C, it's not readily usable from anything other than C). There is a C header for Bullet, see this old Google Code issue and this GitHub issue, but it’s rather minimalistic (only rigid body), although it may be a good start.
PhysX from Nvidia. Open-source, multi-platform, lots of features.
In parallel to resolving collisions using physics engine (that honors the TCastleRigidBody
and TCastleXxxCollider
behaviors), for some purposes Castle Game Engine can also use an older "simple physics" implementation.
This "simple physics" implementation is fully implemented in CGE, without using Kraft or any other "full-blown" physics engine. Capabilities:
It can resolve collisions with (potentially dynamic) meshes using octrees, constructed for each TCastleScene
or each shape of such scene.
A hierarchical octree structure allows to use precise collisions even for dynamic objects (like creatures). This works if the dynamic object internally is a set of unchanging meshes, and only X3D TTransformNode
transformations change.
Contrast this with our "real physics" implementation, that works only on a hierarchy of TCastleTransform
objects. To support collisions with dynamic objects, you need to use ExposeTransforms
to expose relevant transformations as TCastleTransform
objects.
Can perform simple (non-realistic) gravity. There are no additional possible forces. When the objects collide (IOW, something falls on the ground) it just stops (colliding objects do not "bounce off" each other like in real physics engines).
Objects either collide as a mesh (PreciseCollisions
= true
) or as a box (PreciseCollisions
= false
). In certain cases object may alternatively collide as a sphere (when CollisionSphereRadius
is non-zero).
It is used (for now) by:
FPS (1st person) walk/fly navigation in TCastleWalkNavigation
.
3rd person navigation in TCastleThirdPersonNavigation
.
The TCastleThirdPersonNavigation
can resolve avatar vs world collisions using "real physics" (see TCastleThirdPersonNavigation.ChangeTransformation
, TChangeTransformation
) — it auto-detects whether to do this using "real physics" (when TCastleRigidBody
and TCastleXxxCollider
are present) or using "simple physics described below" (when they are not present).
The TCastleThirdPersonNavigation
resolves camera vs world collisions, for now, always using "simple physics". So it is important to set PreciseCollisions
to true
on relevant scenes to let camera travel when it should.
API to query for collisions in world-space coordinates using Viewport.Items.WorldXxx
methods, like
API to query for collisions in coordinates of particular transform parent using TCastleViewport
methods, like:
The long-term goal is to completely remove this "simple physics" implementation in CGE. All it’s functions can be, or will be, possible to achieve using "real physics engine" (like Kraft). But for the time being, some functions are still realized using this "simple physics". The relevant properties are:
TCastleSceneCore.PreciseCollisions
:
false
indicates that scene collides as its bounding box.
true
indicates that we build and update a collision structure (octree) reflecting precisely the triangles in the scene. So the scene collides as a precise set of triangles.
Note
|
The value doesn’t matter at design-time (in CGE editor). To have reliable object picking in editor, at design-time we internally always create collisions strutures, ignoring TCastleSceneCore.PreciseCollisions value. Otherwise picking smaller scenes (like creatures inside a level) would be impossible in some cases, because the big level scene would collide as a big box that includes everything.
|
TCastleTransform.Collides
. By default this is true
. When it is false
, the transformation object (and all its children) does not collide at all.
This affects all collision routines except RayCollision
and RayCast
that look at TCastleTransform.Pickable
.
TCastleTransform.Pickable
. By default this is true
. When it is false
, the transformation object (and all its children) does not affect the results of ray collision (RayCollision
and RayCast
).
Note: when both TCastleTransform.Collides
and TCastleTransform.Pickable
are false
, then TCastleSceneCore.PreciseCollisions
doesn’t matter. In such case, the object will not collide ever (neither as bounding box, nor as a precise mesh).
TCastleTransform.Gravity
. When true
, the relevant object falls down according to (non-realistic) gravity. It will honor (be stopped by) other objects that have Collides
= true
.
TCastleWalkNavigation.Gravity
. When true
, the player avatar falls down according to (non-realistic) gravity. It will honor (be stopped by) other objects that have Collides
= true
.
In the long-term, all these properties/methods will be
deprecated (and later removed)
or they will switch to using physics. They will honor whatever colliders you configure using the TCastleRigidBody
and TCastleXxxCollider
behaviors, and nothing more. And they will honor physics layers.
So all collisions and all gravity should be done using physics engine.
To improve this documentation just edit this page and create a pull request to cge-www repository.