Skip to content

Rigid Bodies

The Rigid Body component (SRigidBodyComponent) makes an entity simulate. Its most important setting is the body type.

Body typeMoves?Use for
StaticNeverFloors, walls, level geometry.
KinematicOnly when you move itPlatforms, doors, scripted movers.
DynamicYes, fully simulatedCrates, props, anything that falls and bounces.

A dynamic body needs a collider with volume to get its mass. Static and kinematic bodies are not pushed by collisions, but dynamic bodies still collide with them.

PropertyWhat it does
Body TypeStatic, Kinematic, or Dynamic (above).
Mass / Override MassMass in kg. By default it is computed from the collider’s volume and density; turn on Override Mass to set Mass directly.
Use GravityTurn off for projectiles or floating objects.
Linear / Angular DampingDrag that bleeds off movement and spin over time.
Restitution OverrideBounciness, 0 (no bounce) to 1 (perfectly elastic).
Friction OverrideSurface grip.
Center Of Mass OffsetShift the balance point; lower it for car-like stability.
Allow SleepingLet a body that comes to rest stop simulating, which saves cost.
Is SensorDetect overlaps without a physical response, a whole-body trigger.
Motion Quality0 = Discrete (cheap); 1 = LinearCast, which stops fast bodies tunneling through thin walls.
Max Linear / Angular VelocitySpeed caps (m/s and rad/s).
Collision ProfileThe layer and mask that decide what this body collides with, see Collisions & Triggers.

Every property above is readable and writable at runtime. In C++ you reach the component through the system context; in C# you reach it through Registry.

SRigidBodyComponent& Body = Context.Get<SRigidBodyComponent>(Entity);
Body.LinearDamping = 0.2f;
Body.bUseGravity = false;

Both hand back the live component, so writing a field writes through to the entity’s data.

Forces do not go through the component, they go through the physics scene, keyed by entity. The entity needs a rigid body for these to do anything; calls on a body-less entity are safe (mutators no-op, getters return zero).

Physics::IPhysicsScene* Scene = Context.GetPhysicsScene();
Scene->AddImpulse(Entity, FVector3(0.0f, 5.0f, 0.0f));
Scene->AddForceAtPosition(Entity, Force, WorldPoint);

GetPhysicsScene() returns null in a world with no physics (the editor world), so null-check it before a call that is not on the simulated path.

MethodEffect
AddForce(entity, force)World-space force (N) for one step
AddImpulse(entity, impulse)Instantaneous impulse (kg·m/s)
AddTorque(entity, torque)Torque (N·m) for one step
AddAngularImpulse(entity, impulse)Instantaneous angular impulse
AddForceAtPosition(entity, force, point)Force at a world point (adds spin)
AddImpulseAtPosition(entity, impulse, point)Impulse at a world point

Apply forces before the physics step and they accumulate onto it. In C++ that means a system that runs in PrePhysics; in C# it means OnUpdate.

REFLECT(System)
struct SHoverSystem
{
GENERATED_BODY()
ENTITY_SYSTEM(RequiresUpdate(EUpdateStage::PrePhysics))
static void Update(const FSystemContext& Context) noexcept
{
Physics::IPhysicsScene* Scene = Context.GetPhysicsScene();
if (Scene == nullptr)
{
return;
}
Context.ForEach<SHoverComponent>([&](ECS::FEntity E, SHoverComponent&)
{
Scene->AddForce(E, FVector3(0.0f, 20.0f, 0.0f));
});
}
};
Scene->SetLinearVelocity(Entity, FVector3(0.0f, 0.0f, 10.0f));
FVector3 Velocity = Scene->GetLinearVelocity(Entity);
MethodEffect
SetLinearVelocity(entity, v)Replace linear velocity (m/s)
SetAngularVelocity(entity, v)Replace angular velocity (rad/s)
GetLinearVelocity(entity) / GetAngularVelocity(entity)Read it back (FVector3)
GetVelocityAtPoint(entity, point)Velocity of a world point on the body
MethodReturns / effect
GetBodyPosition(entity) / GetBodyRotation(entity)The true physics pose
GetCenterOfMass(entity)World-space center of mass
GetEntityBodyID(entity)The Jolt body id (0xFFFFFFFF if no body)
ActivateBody(bodyId) / DeactivateBody(bodyId)Wake or sleep the body
SetGravityFactor(entity, factor)Per-body gravity multiplier (0 = float, 1 = normal)

The C# World.Physics facade names the body accessor GetBodyId(entity) and takes an entity for ActivateBody / DeactivateBody; the C++ scene calls it GetEntityBodyID(entity) and its activate calls take the body id.