RigidBody: forces, impulses and controlled resets
Control a body through physics: mass, contacts, _IntegrateForces, sleep, Freeze and orientation.
Choose a control method
RigidBody2D/3D simulates forces and contacts. A CharacterBody often better suits a code-controlled character with explicit speed/slope rules. Do not assign a dynamic RigidBody Position every _Process: rendering, integration and contacts will compete over its state.
| Task | Method |
|---|---|
| One-off push | ApplyCentralImpulse once per event |
| Continuous thrust | ApplyCentralForce every required physics tick |
| Persistent contribution | ConstantForce / AddConstantCentralForce; explicitly clear it |
| Offset push/force | ApplyImpulse/ApplyForce; the offset affects torque |
| Custom integration or teleport | _IntegrateForces and PhysicsDirectBodyState |
Force is already integrated over time; do not multiply it by delta before ApplyCentralForce. An impulse is not multiplied by delta either and should not be applied every frame to represent continuous thrust. For a free body without damping, a central impulse changes velocity by impulse / mass: impulse 10 and mass 2 give 5 units/s. Contacts, constraints and damping can change the observed result.
Run a body and reset it
Use the complete 2D and 3D levels to see the floor, contacts and controls. For your own body, add the appropriate class below, attach it to a RigidBody2D or RigidBody3D and add a direct CollisionShape child with nonzero geometry. RequestReset accepts a world position. It does not change Transform immediately: the callback applies it on a physics tick and clears velocities. Unfreeze first if needed; the request does not bypass simulation mode.
LabBody2D.cs
using System;
using Reckfell;
public partial class LabBody2D : RigidBody2D
{
private Vector2? _resetPosition;
public int ResetCount { get; private set; }
public void RequestReset(Vector2 worldPosition)
{
if (!worldPosition.IsFinite()) throw new ArgumentOutOfRangeException(nameof(worldPosition));
_resetPosition = worldPosition;
Sleeping = false;
}
public override void _IntegrateForces(PhysicsDirectBodyState2D state)
{
if (_resetPosition is not Vector2 position) return;
state.Transform = new Transform2D(0, position);
state.LinearVelocity = Vector2.Zero;
state.AngularVelocity = 0;
_resetPosition = null;
ResetCount++;
}
}LabBody3D.cs
using System;
using Reckfell;
public partial class LabBody3D : RigidBody3D
{
private Vector3? _resetPosition;
public int ResetCount { get; private set; }
public void RequestReset(Vector3 worldPosition)
{
if (!worldPosition.IsFinite()) throw new ArgumentOutOfRangeException(nameof(worldPosition));
_resetPosition = worldPosition;
Sleeping = false;
}
public override void _IntegrateForces(PhysicsDirectBodyState3D state)
{
if (_resetPosition is not Vector3 position) return;
state.Transform = new Transform3D(Basis.Identity, position);
state.LinearVelocity = Vector3.Zero;
state.AngularVelocity = Vector3.Zero;
_resetPosition = null;
ResetCount++;
}
}Separately restore health, timers and child visuals when resetting a whole game object. The example resets one body's physics state only. Under a moved/rotated parent, obtain world coordinates through ToGlobal. Do not assign a global transform as a child's local transform. ResetPhysicsInterpolation addresses visual interpolation after teleport separately; it does not replace velocity reset.
Contacts and resting state
For RigidBody BodyEntered/BodyExited, enable ContactMonitor and set MaxContactsReported above zero. This is a contact limit, not a promise of that many unique bodies; one body can contribute several points. Detection does not permit immediate structural changes inside the callback; defer them.
Sleeping is simulation sleep; Freeze selects a frozen mode. Neither equals shape Disabled. A frozen shape can remain an obstacle. FreezeMode.Static and Kinematic differ when moved manually; consider AnimatableBody for a regularly moving platform. Inspect the next physics state rather than the statement immediately after a mode change.
CustomIntegrator disables standard force integration for the body; it does not disable all contacts. With it enabled, calculate the needed gravity/forces through state or deliberately invoke standard integration. LockRotation prevents ordinary rotation but does not replace checking geometry and centre of mass.
Turn toward a target
For a physical turn, calculate direction error and control angular velocity/torque in the physics phase with bounded speed and coefficients. Repeated LookAt on a dynamic body forces its orientation and can undermine expected contact response. Rotate a separate visual child if only the image needs to turn. Handle degenerate directions, the model axis and shortest rotation separately; the reset example deliberately restores identity orientation and does not implement a servo.
Diagnose unexpected results
No motion: check Freeze, Sleeping, axis locks, mass, timing and actual force. No signal: inspect ContactMonitor, contact limit, filters and shape. Jitter: look for competing Transform writes, initial penetration and extreme mass ratios. A fast object passing through a wall needs thickness, tick and CCD checks; larger mass alone does not fix discrete detection.