Class TCastleRigidBody

Unit

Declaration

type TCastleRigidBody = class(TCastleBehavior)

Description

Use this behavior to be affected by physics collisions and forces. Add a TCastleRigidBody and some collider (TCastleCollider descendant) as behaviors of TCastleTransform to make the given TCastleTransform be affected by physics and collide with other physics bodies.

Hierarchy

Overview

Methods

Protected procedure WorldAfterAttach; override;
Protected procedure WorldBeforeDetach; override;
Protected procedure Update(const SecondsPassed: Single; var RemoveMe: TRemoveType); override;
Protected function CanAttachToParent(const NewParent: TCastleTransform; out ReasonWhyCannot: String): Boolean; override;
Public constructor Create(AOwner: TComponent); override;
Public destructor Destroy; override;
Public procedure Setup2D;
Public function GetCollidingTransforms: TCastleTransformList;
Public function PhysicsRayCast(const RayOrigin, RayDirection: TVector3; const MaxDistance: Single = MaxSingle): TPhysicsRayCastResult;
Public function PropertySections(const PropertyName: String): TPropertySections; override;
Public procedure AddForceAtPosition(const Force, Position: TVector3);
Public procedure AddForce(const Force: TVector3; const ForceInLocalCoordinates: Boolean);
Public procedure AddTorque(const Torque: TVector3);
Public procedure ApplyImpulse(const Impulse, Point: TVector3);
Public function ExistsInRoot: Boolean;
Public procedure WakeUp;

Properties

Public property AngularVelocity: TVector3 read FAngularVelocity write SetAngularVelocity;
Public property LinearVelocity: TVector3 read FLinearVelocity write SetLinearVelocity;
Public property InitialAngularVelocity: TVector3 read FAngularVelocity write SetAngularVelocity; deprecated 'use AngularVelocity';
Public property InitialLinearVelocity: TVector3 read FLinearVelocity write SetLinearVelocity; deprecated 'use LinearVelocity';
Public property OnCollisionEnter: TCollisionEvent read FOnCollisionEnter write SetOnCollisionEnter;
Public property OnCollisionExit: TCollisionEvent read FOnCollisionExit write SetOnCollisionExit;
Public property OnCollisionStay: TCollisionEvent read FOnCollisionStay write SetOnCollisionStay;
Published property Dynamic: Boolean read FDynamic write SetDynamic default true;
Published property Animated: Boolean read FAnimated write SetAnimated default false;
Published property Trigger: Boolean read FTrigger write SetTrigger default false;
Published property CollisionDetection: TCollisionDetection read FCollisionDetection write SetCollisionDetection default cdDiscrete;
Published property Layer: TPhysicsLayer read FLayer write SetLayer default 0;
Published property Gravity: Boolean read FGravity write SetGravity default true;
Published property LockTranslation: T3DCoords read FLockTranslation write SetLockTranslation default [];
Published property LockRotation: T3DCoords read FLockRotation write SetLockRotation default [];
Published property Exists: Boolean read FExists write SetExists default true;
Published property AngularVelocityDamp: Single read FAngularVelocityDamp write SetAngularVelocityDamp default 0.1;
Published property MaxAngularVelocity: Single read FMaxAngularVelocity write SetMaxAngularVelocity;
Published property LinearVelocityDamp: Single read FLinearVelocityDamp write SetLinearVelocityDamp default 0.1;
Published property MaxLinearVelocity: Single read FMaxLinearVelocity write SetMaxLinearVelocity;
Published property AngularVelocityPersistent: TCastleVector3Persistent read FAngularVelocityPersistent ;
Published property LinearVelocityPersistent: TCastleVector3Persistent read FLinearVelocityPersistent ;

Description

Methods

Protected procedure WorldAfterAttach; override;

Initializes physics engine objects when TCastleRigidBody is attached to world.

Protected procedure WorldBeforeDetach; override;

Deinitializes physics engine objects when TCastleRigidBody is attached to world.

Protected procedure Update(const SecondsPassed: Single; var RemoveMe: TRemoveType); override;

This item has no description. Showing description inherited from TCastleBehavior.Update.

Continuously occuring event, for various tasks.

Protected function CanAttachToParent(const NewParent: TCastleTransform; out ReasonWhyCannot: String): Boolean; override;

Only one TCastleRigidBody behavior can be added to a given TCastleTransform so we check that here.

Public constructor Create(AOwner: TComponent); override;

This item has no description.

Public destructor Destroy; override;

This item has no description.

Public procedure Setup2D;

Utility function to set common values for physics in 2D games. Locks moving along the Z axis, locks rotating along the X and Y axes.

Public function GetCollidingTransforms: TCastleTransformList;

Transformations that we collide with currently.

Public function PhysicsRayCast(const RayOrigin, RayDirection: TVector3; const MaxDistance: Single = MaxSingle): TPhysicsRayCastResult;

First object hit by the ray, calculated using the physics engine.

Returns the TPhysicsRayCastResult record. Read TPhysicsRayCastResult.Hit (boolean), TPhysicsRayCastResult.Transform (guaranteed to be Nil when TPhysicsRayCastResult.Hit is False) and other fields to know what was hit.

The given RayOrigin, RayDirection, MaxDistance are in the parent coordinate system of associated TCastleTransform (TCastleBehavior.Parent). So for example query like this works naturally:

RBody := MyTransform.FindBehavior(TCastleRigidBody) as TCastleRigidBody;
Hit := RBody.RayCast(MyTransform.Translation, MyTransform.Direction, MaxDistance);

It returns TPhysicsRayCastResult, with information there consistently in the same coordinate system as inputs. So TPhysicsRayCastResult.Distance, TPhysicsRayCastResult.Point, TPhysicsRayCastResult.Normal are in parent coordinate system of associated TCastleTransform (TCastleBehavior.Parent).

This ignores the collider of this rigid body (to not accidentally collide with your own collider), and checks collisions with the rest of the world in given max distance. Only collisions with the physics colliders (TCastleCollider) are considered.

Note: The TCastleTransform.Pickable property is ignored by this method, i.e. it considers all colliders regardless of their TCastleTransform.Pickable value. The TCastleTransform.Pickable is only taken into account by the routines of the old physics system (see https://castle-engine.io/physics#_old_system_for_collisions_and_gravity ). In the new system, a similar role will be filled by layers.

Public function PropertySections(const PropertyName: String): TPropertySections; override;

This item has no description. Showing description inherited from TCastleComponent.PropertySections.

Section where to show property in the editor.

Public procedure AddForceAtPosition(const Force, Position: TVector3);

Push this rigid body. The body is pushed from a Position and along the direction of Force. Longer length of Force makes a stronger push.

The forces affecting each body are reset every frame (only the body velocity is preserved across frames). If you want to keep applying this force (e.g. it is a wind that continues pushing in given direction) you should call this method every frame. It automatically accounts for the delta time (because the force will actually be applied later, with delta time, to velocity) so no need to multiply the arguments with SecondsPassed. That is, adding force means Velocity += Force * SecondsPassed / Mass.

By changing Position from which you push, you can change the angular velocity, i.e. different Position makes the body spin in different ways. Note that Position too distant from the body center may result in unrealistically strong push. If Position is exactly at body center, then angular velocity will not be affected.

Force and Position are in the world coordinate system.

Public procedure AddForce(const Force: TVector3; const ForceInLocalCoordinates: Boolean);

Push this rigid body. The body is pushed along the direction of Force. Longer length of Force makes a stronger push.

This is similar to AddForceAtPosition, but the Force (direction) can be in local or global coordinate system (depending on ForceInLocalCoordinates). Moreover it doesn't take as parameter any Position: the force always acts from the origin of this body.

Just like with AddForceAtPosition, the forces affecting each body are reset every frame (only the body velocity is preserved across frames). If you want to keep applying this force (e.g. it is a wind that continues pushing in given direction) you should call this method every frame. It automatically accounts for the delta time (because the force will actually be applied later, with delta time, to velocity) so no need to multiply the arguments with SecondsPassed.

Public procedure AddTorque(const Torque: TVector3);

Rotate this rigid body with physics. Longer length of Torque makes a stronger push. Torque is in world coordinates.

Just like with AddForceAtPosition, the forces affecting each body are reset every frame (only the body velocity is preserved across frames). If you want to keep applying this force (e.g. it is a whirlwind that continues rotating) you should call this method every frame. It automatically accounts for the delta time (because the force will actually be applied later, with delta time, to velocity) so no need to multiply the arguments with SecondsPassed.

Public procedure ApplyImpulse(const Impulse, Point: TVector3);

Apply a one-time instant increase in speed, that pushes the body (increasing velocity). Impulse is a direction along which to push, Point is the position from which you push. Longer length of Impulse makes a stronger push.

Impulse and Point are both in world coordinates.

Adding impulse means Velocity += Force / Mass. To be more precise, adding impulse directly increases LinearVelocity and AngularVelocity. Unlike AddForceAtPosition, the velocity increase is not multiplied by the delta of time, so it is not expected you will call this every frame. (If you do, you should take care to multiply Impulse by SecondsPassed.)

Same notes as for Position of AddForceAtPosition: By changing Point from which you push, you can change the angular velocity, i.e. different Point makes the body spin in different ways. Note that Point too distant from the body center may result in unrealistically strong push. If Point is exactly at body center, then angular velocity will not be affected.

Public function ExistsInRoot: Boolean;

Returns true when rigid body behavior exists, and is added to Castle Transform, and this transform ExistsInRoot = true.

Public procedure WakeUp;

For performance, physics engine sometimes puts some body to "sleep", which means it will not move anymore, because it didn't move (much) in the recent frames. In general, the body should be "woken up" automatically when something collides with it, so the mechanism should be invisible to you... but sometimes it is necessary to wake up a body explicitly.

Properties

Public property AngularVelocity: TVector3 read FAngularVelocity write SetAngularVelocity;

Current rotating velocity of this body. You can query it (as it changes, affected by forces) and set it at any point. In world coordinates.

See https://en.wikipedia.org/wiki/Angular_velocity about the exact meaning of angular velocity. The vector direction (AngularVelocity.Normalize) determines the axis around which we rotate. The vector length (AngularVelocity.Length) determines the speed (in radians/second) with which we rotate.

Public property LinearVelocity: TVector3 read FLinearVelocity write SetLinearVelocity;

Current moving velocity of this body. You can query it (as it changes, affected by forces) and set it at any point. In world coordinates.

Public property InitialAngularVelocity: TVector3 read FAngularVelocity write SetAngularVelocity; deprecated 'use AngularVelocity';

Warning: this symbol is deprecated: use AngularVelocity

This item has no description.

Public property InitialLinearVelocity: TVector3 read FLinearVelocity write SetLinearVelocity; deprecated 'use LinearVelocity';

Warning: this symbol is deprecated: use LinearVelocity

This item has no description.

Public property OnCollisionEnter: TCollisionEvent read FOnCollisionEnter write SetOnCollisionEnter;

Occurs when TCastleRigidBody starts colliding with another TCastleRigidBody.

It can occur repeatedly for the same body (in the same time instant) if the collision has many points of contact.

Warning: Do not free the related TCastleTransform or TCastleRigidBody or TCastleCollider components upon receiving this event. Right now, it would free an underlying physics engine object, and this would crash the physics engine.

Instead, you can:

Public property OnCollisionExit: TCollisionEvent read FOnCollisionExit write SetOnCollisionExit;

Occurs when TCastleRigidBody stops colliding with another TCastleRigidBody.

Just like at OnCollisionEnter: Do not free the related components upon receiving this event. See the OnCollisionEnter documentation for details of this limitation and solutions.

Public property OnCollisionStay: TCollisionEvent read FOnCollisionStay write SetOnCollisionStay;

Occurs when TCastleRigidBody still collides with another TCastleRigidBody.

Just like at OnCollisionEnter: Do not free the related components upon receiving this event. See the OnCollisionEnter documentation for details of this limitation and solutions.

Published property Dynamic: Boolean read FDynamic write SetDynamic default true;

Does the physics simulation move and rotate this object (because of gravity, or because it collides with others).

When False the object is not transformed by the physics simulation. It still collides with other physical objects. So it's a static collidable body that will not move on any collision / force.

Published property Animated: Boolean read FAnimated write SetAnimated default false;

Is the transformation of this object updated often (relevant only when Dynamic = False).

This property is taken into account only if Dynamic = False.

This property is an optimization hint to the physics engine, it says how often you will change the transformation.

true (animated object, also known as "kinematic")

The physics engine is prepared that this object can move often, e.g. every frame, so you can animate the related TCastleTransform using any technique.

false (static object)

Changing the transformation properties is costly, it may even be like destroying this object and creating a new one from the point of view of the physics engine, so do not change the transformation often, e.g. every frame.

The upside is that collisions with static objects may be much more optimized, since the physics engine can assume that all the static objects form a completely frozen unmovable geometry in the world.

Published property Trigger: Boolean read FTrigger write SetTrigger default false;

Triggers report when other object collides with them, but still allow the other object to pass through. In other words, colliding with a trigger will not cause the collider to stop or "bounce off" the trigger.

They are useful as sensors. E.g. a trigger may be a coin (like in "Mario") that the player can "consume" by colliding with it.

Triggers report collisions through the same events as other rigid bodies: (TCastleRigidBody.OnCollisionEnter, TCastleRigidBody.OnCollisionStay, TCastleRigidBody.OnCollisionExit).

Published property CollisionDetection: TCollisionDetection read FCollisionDetection write SetCollisionDetection default cdDiscrete;

Sets CollisionDetectionMode in rigid body to Discrete or ContinuousSweep.

Published property Layer: TPhysicsLayer read FLayer write SetLayer default 0;

Physics layer of the rigid body determines with which other bodies it may collide.

The way layers interact is configured in the MyViewport.Items.PhysicsProperties.LayerCollisions.

Each layer can also have name and description. You can set them using the MyViewport.Items.PhysicsProperties.LayerNames property.

Published property Gravity: Boolean read FGravity write SetGravity default true;

Is this object affected by gravity.

Published property LockTranslation: T3DCoords read FLockTranslation write SetLockTranslation default [];

Disable motion (TCastleTransform.Translation change) along the particular (world) axis.

For 2D games, you will usually want to disable motion along the Z axis. Instead of directly changing this property, you can achieve this by calling Setup2D.

Published property LockRotation: T3DCoords read FLockRotation write SetLockRotation default [];

Disable rotation (TCastleTransform.Rotation change) along the particular (world) axis.

For 2D games, you will usually want to disable rotation along the X and Y axes. Instead of directly changing this property, you can achieve this by calling Setup2D.

Published property Exists: Boolean read FExists write SetExists default true;

Controls whether the rigid body is actually processed by the physics engine. When this is False, the rigid body is not updated by the physics engine, it does not cause collisions with other rigid bodies and it does not receive events like OnCollisionEnter, OnCollisionStay, OnCollisionExit.

Published property AngularVelocityDamp: Single read FAngularVelocityDamp write SetAngularVelocityDamp default 0.1;

Damping means that the velocity will decrease over time. AngularVelocityDamp causes AngularVelocity to decrease over time. For the exact equations how it works, see LinearVelocityDamp.

Published property MaxAngularVelocity: Single read FMaxAngularVelocity write SetMaxAngularVelocity;

This item has no description.

Published property LinearVelocityDamp: Single read FLinearVelocityDamp write SetLinearVelocityDamp default 0.1;

Damping means that the velocity will decrease over time. LinearVelocityDamp causes LinearVelocity to decrease over time, similar AngularVelocityDamp causes AngularVelocity to decrease over time.

Values from 0.0 up to infinity make sense.

Exact interpretation:

The damping is applied every "physics frame" following this equation:

LinearVelocity := LinearVelocity * 1 / (1 + LinearVelocityDamp * 1/PhysicsProperties.Frequency)

Where PhysicsProperties.Frequency is by default 60, and can be customized for each viewport using Viewport.Items.PhysicsProperties.Frequency. The frequency also determines how often do "physics frames" occur.

In effect, damping = 0 means that no damping occurs.

Damping values > 0 means that LinearVelocity decreases with time, larger LinearVelocityDamp -> the faster LinearVelocity will decrease.

The meaning of damping = 1.0 depends on Viewport.Items.PhysicsProperties.Frequency:

  • With TPhysicsProperties.Frequency = 60 (default), the XxxVelocityDamp = 1.0 implies that the velocity drops to ~0.37 of original after 1 second.

  • With TPhysicsProperties.Frequency = 1 (crazy small, just giving it as example), the XxxVelocityDamp = 1.0 implies that the velocity drops to half of original after 1 second.

  • With TPhysicsProperties.Frequency = 10000 (crazy large, just giving it as example), the XxxVelocityDamp = 1.0 implies that the velocity drops to ~0.36 of original after 1 second.

Published property MaxLinearVelocity: Single read FMaxLinearVelocity write SetMaxLinearVelocity;

This item has no description.

Published property AngularVelocityPersistent: TCastleVector3Persistent read FAngularVelocityPersistent ;

AngularVelocity that can be visually edited in Castle Game Engine Editor, Lazarus and Delphi. Normal user code does not need to deal with this, instead read or write AngularVelocity directly.

See also
AngularVelocity
Current rotating velocity of this body.
Published property LinearVelocityPersistent: TCastleVector3Persistent read FLinearVelocityPersistent ;

LinearVelocity that can be visually edited in Castle Game Engine Editor, Lazarus and Delphi. Normal user code does not need to deal with this, instead read or write LinearVelocity directly.

See also
LinearVelocity
Current moving velocity of this body.

Generated by PasDoc 0.16.0-snapshot.