Table of Contents

Class World

Namespace
Jitter2
Assembly
Jitter2.dll

Contains the bodies, contacts, and constraints of a physics simulation.

public sealed class World : IDisposable
Inheritance
World
Implements
Inherited Members

Remarks

Do not step or modify the same world from multiple threads at once. Different worlds can run concurrently with multiThread: false. Multithreaded steps share a worker pool and wait for each other, even when they belong to different worlds.

Constructors

World()

Creates an instance of the World class.

public World()

Properties

AllowDeactivation

Whether bodies can go to sleep when they stop moving. Default is true. Setting this to false does not wake bodies that are already asleep.

public bool AllowDeactivation { get; set; }

Property Value

bool

BroadPhaseFilter

A filter that can reject shape pairs before testing them for collisions. Default is null.

public IBroadPhaseFilter? BroadPhaseFilter { get; set; }

Property Value

IBroadPhaseFilter

Remarks

Use this for collision layers or custom proxy types. With multithreaded stepping, calls can run concurrently, so the filter must be thread-safe.

CcdIterations

Number of continuous collision detection (CCD) passes per step. Default is 4.

public int CcdIterations { get; set; }

Property Value

int

Remarks

More passes can catch additional collisions caused by earlier collision responses, at a higher cost. No finite number guarantees that every collision is found. Applies to bodies with EnableCcd enabled.

Exceptions

ArgumentOutOfRangeException

The value is less than one.

CcdRelaxationFactor

Fraction of the predicted gap that CCD contacts allow to close during one step. Default is 0.9.

[Obsolete("Use ContactSettings.CcdRelaxationFactor instead.")]
public float CcdRelaxationFactor { get; set; }

Property Value

float

Remarks

Obsolete: use CcdRelaxationFactor through ContactSettings.

CcdVelocityThreshold

Minimum relative surface speed for continuous collision detection, in world units per second. Nearly stationary pairs below this threshold are skipped. Default is 0.1.

public float CcdVelocityThreshold { get; set; }

Property Value

float

Remarks

The speed estimate includes both translation and rotation. Set to zero to include even slow-moving pairs.

ContactSettings

Solver settings shared by all contacts of this world, such as the penetration correction and the restitution threshold. Modify the fields in place; every contact reads them when it is prepared.

public ref ContactSettings ContactSettings { get; }

Property Value

ContactSettings

Remarks

The settings live in unmanaged memory owned by the world. Do not keep the reference across a Dispose() call.

Exceptions

ObjectDisposedException

Thrown if this world has been disposed.

DebugTimings

Contains timings for the stages of the last call to Step(float, bool). Values are in milliseconds. Index using (int)Timings.XYZ.

public ReadOnlySpan<double> DebugTimings { get; }

Property Value

ReadOnlySpan<double>

DynamicTree

The broad phase of this world. It holds a proxy for every shape attached to a body, and can also hold proxies added by the application. Update a shape's proxy after changing its geometry.

public DynamicTree DynamicTree { get; }

Property Value

DynamicTree

EnableAuxiliaryContactPoints

Builds a full contact manifold for each touching pair instead of registering only the single deepest point. Default is true.

public bool EnableAuxiliaryContactPoints { get; set; }

Property Value

bool

Remarks

The manifold covers the whole touching area: the corners of touching faces, the two ends of the line on which a capsule or cylinder rests, the point below a sphere. This keeps stacks stable. Rolling also needs it: the narrow phase point is slightly off on curved surfaces, so a sphere, capsule or cylinder rolling on that point alone slows down. See CollisionManifold.

Gravity

Default gravity, see also AffectedByGravity. Default value: (0, -9.81, 0).

public JVector Gravity { get; set; }

Property Value

JVector

IsDisposed

Gets a value indicating whether this world has been disposed.

public bool IsDisposed { get; }

Property Value

bool

Islands

All collision islands in this world.

public ReadOnlyPartitionedSet<Island> Islands { get; }

Property Value

ReadOnlyPartitionedSet<Island>

NarrowPhaseFilter

A filter that can reject collisions or adjust contact points and normals. Defaults to TriangleEdgeCollisionFilter.

public INarrowPhaseFilter? NarrowPhaseFilter { get; set; }

Property Value

INarrowPhaseFilter

Remarks

Called after a collision is detected. With multithreaded stepping, calls can run concurrently, so the filter must be thread-safe.

NullBody

A static body to use as one endpoint when attaching a constraint to the world.

public RigidBody NullBody { get; }

Property Value

RigidBody

PersistentContactManifold

Reuses contact points and impulses from previous steps to improve resting stability. Default is true. When false, contacts are discarded at the end of each step, which can require more solver iterations to achieve the same stability.

public bool PersistentContactManifold { get; set; }

Property Value

bool

RawData

Provides direct access to the world's unmanaged simulation data. Prefer the properties on RigidBody, Constraint, and Arbiter for normal use.

public World.SpanData RawData { get; }

Property Value

World.SpanData

Remarks

Spans must not be retained across world changes or accessed while the world is being stepped. See World.SpanData for lifetime restrictions.

Exceptions

ObjectDisposedException

Thrown if this world has been disposed.

RigidBodies

All rigid bodies in this world.

public ReadOnlyPartitionedSet<RigidBody> RigidBodies { get; }

Property Value

ReadOnlyPartitionedSet<RigidBody>

SolveMode

The solver strategy used during Step(float, bool). Defaults to Regular.

public SolveMode SolveMode { get; set; }

Property Value

SolveMode

Remarks

Deterministic can be significantly slower than Regular.

Exceptions

ArgumentOutOfRangeException

Thrown when an undefined SolveMode value is assigned.

SolverIterations

Gets or sets the number of iterations per substep for the constraint solver and velocity relaxation.

public (int solver, int relaxation) SolverIterations { get; set; }

Property Value

(int solver, int relaxation)

Remarks

Higher solver iterations improve constraint accuracy at the cost of performance. Relaxation iterations solve the contacts again after the bodies have moved, this time without pushing overlapping bodies apart, so that the push does not remain as extra velocity. Default value: (solver: 6, relaxation: 4).

Exceptions

ArgumentOutOfRangeException

Thrown if solver is less than 1 or relaxation is negative.

SubstepCount

The number of substeps for each call to Step(float, bool). Sub-stepping is deactivated when set to one. Default value: 1.

public int SubstepCount { get; set; }

Property Value

int

Exceptions

ArgumentOutOfRangeException

Thrown when the assigned value is less than one.

ThreadModel

Gets or sets the threading model used between calls to Step(float, bool).

public World.ThreadModelType ThreadModel { get; set; }

Property Value

World.ThreadModelType

Exceptions

ArgumentOutOfRangeException

Thrown when an undefined World.ThreadModelType value is assigned.

Methods

Clear()

Removes all entities from the simulation world. Also clears all proxies from the dynamic tree, including any user-added proxies not owned by the world.

public void Clear()

CreateConstraint<T>(RigidBody, RigidBody)

Constructs a constraint of the specified type. After creation, initialize the constraint by calling its Initialize method.

public T CreateConstraint<T>(RigidBody body1, RigidBody body2) where T : Constraint, new()

Parameters

body1 RigidBody

The first rigid body involved in the constraint.

body2 RigidBody

The second rigid body involved in the constraint.

Returns

T

A new instance of the specified constraint type, already registered with the world.

Type Parameters

T

The specific type of constraint to create.

Exceptions

ArgumentException

Thrown if either body does not belong to this world.

SameBodyException

Thrown if body1 and body2 are the same.

PartitionedBuffer<T>.MaximumSizeException

Raised when the constraint buffer maximum size is exceeded.

CreateRigidBody()

Creates and adds a new rigid body to the simulation world.

public RigidBody CreateRigidBody()

Returns

RigidBody

A newly created instance of RigidBody.

Exceptions

PartitionedBuffer<T>.MaximumSizeException

Raised when the rigid-body buffer maximum size is exceeded.

DefaultDynamicTreeFilter(IDynamicTreeProxy, IDynamicTreeProxy)

Default filter function for the DynamicTree. Rejects two RigidBodyShape proxies attached to the same body; accepts other proxy pairs.

public static bool DefaultDynamicTreeFilter(IDynamicTreeProxy proxyA, IDynamicTreeProxy proxyB)

Parameters

proxyA IDynamicTreeProxy
proxyB IDynamicTreeProxy

Returns

bool

Dispose()

Releases all unmanaged memory buffers used by this simulation world.

public void Dispose()

Remarks

After disposal, the world instance is unusable. All bodies, constraints, and contacts become invalid. Calling Dispose() multiple times is safe.

ForceSleepIsland(Island)

Immediately puts a group of connected bodies to sleep.

public void ForceSleepIsland(Island island)

Parameters

island Island

The island to deactivate.

Remarks

Works even when AllowDeactivation is false. Clears velocities and pending forces and torques on the island's dynamic and kinematic bodies.

Exceptions

ArgumentNullException

Thrown if island is null.

ArgumentException

Thrown if island does not belong to this world.

GetArbiter(ulong, ulong, out Arbiter)

Gets an existing Arbiter instance for the given pair of IDs.

public bool GetArbiter(ulong id0, ulong id1, out Arbiter arbiter)

Parameters

id0 ulong

The first identifier (e.g., shape ID).

id1 ulong

The second identifier.

arbiter Arbiter

The arbiter for the ordered ID pair, or null if none exists.

Returns

bool

true if an arbiter exists for the ordered ID pair; otherwise, false.

Remarks

The order of id0 and id1 matters. For arbiters created by the engine, id0 < id1 holds for RigidBodyShapes.

May run concurrently with contact creation and registration. Finish these calls before stepping or modifying the world, including removing arbiters, bodies, or shapes.

GetOrCreateArbiter(ulong, ulong, RigidBody, RigidBody, out Arbiter)

Gets an existing Arbiter instance for the given pair of IDs, or creates a new one if none exists.

public void GetOrCreateArbiter(ulong id0, ulong id1, RigidBody body1, RigidBody body2, out Arbiter arbiter)

Parameters

id0 ulong

The first identifier associated with the contact (e.g., shape or feature ID).

id1 ulong

The second identifier associated with the contact.

body1 RigidBody

The first rigid body. Used only if a new arbiter is created.

body2 RigidBody

The second rigid body. Used only if a new arbiter is created.

arbiter Arbiter

The resulting Arbiter instance associated with the ID pair.

Remarks

The body arguments are used only when creating a new arbiter. Reuse the same IDs and body order when registering contacts for this pair.

Contact creation and registration calls may run concurrently with each other. Finish all such calls before stepping the world, removing arbiters, or adding, removing, or changing simulation objects. Do not overlap them with Clear() or Dispose().

The IDs identify an ordered pair: keep their order consistent between calls.

LockTwoBody(ref RigidBodyData, ref RigidBodyData)

Acquires locks on two rigid bodies using a spin-wait loop. The lock order is determined by memory address to prevent deadlocks.

public static void LockTwoBody(ref RigidBodyData b1, ref RigidBodyData b2)

Parameters

b1 RigidBodyData

Reference to the first rigid body data.

b2 RigidBodyData

Reference to the second rigid body data.

RegisterContact(Arbiter, in JVector, in JVector, in JVector, SolveMode)

Registers a single contact point into an existing Arbiter.

public void RegisterContact(Arbiter arbiter, in JVector point1, in JVector point2, in JVector normal, ContactData.SolveMode removeFlags = SolveMode.None)

Parameters

arbiter Arbiter

The existing Arbiter instance to which the contact will be added.

point1 JVector

The contact point on the first body, in world space.

point2 JVector

The contact point on the second body, in world space.

normal JVector

The contact normal, in world space. Must be a unit vector pointing from the arbiter's first body toward its second body.

removeFlags ContactData.SolveMode

A bitmask of ContactData.SolveMode flags to be removed from the full contact solution (see Full).

Remarks

Contact creation and registration calls may run concurrently with each other. Finish all such calls before stepping the world, removing arbiters, or adding, removing, or changing simulation objects. Do not overlap them with Clear() or Dispose().

Do not pass an arbiter after it has been removed from the world; removed arbiters may be recycled.

RegisterContact(ulong, ulong, RigidBody, RigidBody, in JVector, ref CollisionManifold, SolveMode)

Registers one or more contact points between two rigid bodies using a CollisionManifold, creating an Arbiter if one does not already exist.

public void RegisterContact(ulong id0, ulong id1, RigidBody body1, RigidBody body2, in JVector normal, ref CollisionManifold manifold, ContactData.SolveMode removeFlags = SolveMode.None)

Parameters

id0 ulong

The first identifier associated with the contact (e.g., shape or feature ID).

id1 ulong

The second identifier associated with the contact.

body1 RigidBody

The first rigid body involved in the contact.

body2 RigidBody

The second rigid body involved in the contact.

normal JVector

The contact normal, in world space. Must be a unit vector pointing from body1 toward body2.

manifold CollisionManifold

A CollisionManifold containing contact point pairs in world space.

removeFlags ContactData.SolveMode

A bitmask of ContactData.SolveMode flags to be removed from the full contact solution (see Full).

Remarks

Contact creation and registration calls may run concurrently with each other. Finish all such calls before stepping the world, removing arbiters, or adding, removing, or changing simulation objects. Do not overlap them with Clear() or Dispose().

The IDs identify an ordered pair: keep their order consistent between calls.

RegisterContact(ulong, ulong, RigidBody, RigidBody, in JVector, in JVector, in JVector, SolveMode)

Registers a contact point between two rigid bodies, creating an Arbiter if one does not already exist.

public void RegisterContact(ulong id0, ulong id1, RigidBody body1, RigidBody body2, in JVector point1, in JVector point2, in JVector normal, ContactData.SolveMode removeFlags = SolveMode.None)

Parameters

id0 ulong

The first identifier associated with the contact (e.g., shape or feature ID).

id1 ulong

The second identifier associated with the contact.

body1 RigidBody

The first rigid body involved in the contact.

body2 RigidBody

The second rigid body involved in the contact.

point1 JVector

The contact point on body1, in world space.

point2 JVector

The contact point on body2, in world space.

normal JVector

The contact normal, in world space. Must be a unit vector pointing from body1 toward body2.

removeFlags ContactData.SolveMode

A bitmask of ContactData.SolveMode flags to be removed from the full contact solution (see Full).

Remarks

Contact creation and registration calls may run concurrently with each other. Finish all such calls before stepping the world, removing arbiters, or adding, removing, or changing simulation objects. Do not overlap them with Clear() or Dispose().

The IDs identify an ordered pair: keep their order consistent between calls.

Remove(Arbiter)

Removes a particular arbiter from the world.

public void Remove(Arbiter arbiter)

Parameters

arbiter Arbiter

The arbiter to remove.

Exceptions

ArgumentNullException

Thrown if arbiter is null.

ArgumentException

Thrown if arbiter does not belong to this world.

ObjectDisposedException

Thrown if this world has been disposed.

Remove(Constraint)

Removes a specific constraint from the world. For temporary deactivation of constraints, consider using the IsEnabled property.

public void Remove(Constraint constraint)

Parameters

constraint Constraint

The constraint to be removed.

Exceptions

ArgumentNullException

Thrown if constraint is null.

ArgumentException

Thrown if constraint does not belong to this world.

InvalidOperationException

Thrown if the constraint has already been removed.

ObjectDisposedException

Thrown if this world has been disposed.

Remove(RigidBody)

Removes the specified body from the world. This operation also automatically discards any associated contacts and constraints.

public void Remove(RigidBody body)

Parameters

body RigidBody

The rigid body to remove.

Exceptions

ArgumentNullException

Thrown if body is null.

ArgumentException

Thrown if body does not belong to this world.

InvalidOperationException

Thrown if body has already been removed.

ObjectDisposedException

Thrown if this world has been disposed.

RequestId()

Generates a unique ID.

public static ulong RequestId()

Returns

ulong

A monotonically increasing unique identifier.

RequestId(int)

Generates a range of unique IDs.

public static (ulong min, ulong max) RequestId(int count)

Parameters

count int

The number of IDs to generate.

Returns

(ulong min, ulong max)

A tuple containing the minimum and maximum request IDs in the generated range. The upper bound is exclusive.

Exceptions

ArgumentOutOfRangeException

Thrown when count is less than 1.

Stabilize(float, int, int, bool)

Adjusts velocities to satisfy existing contacts and constraints without moving the bodies.

public void Stabilize(float dt, int solverIterations, int relaxationIterations = 0, bool multiThread = true)

Parameters

dt float

The reference timestep in seconds used to scale bias and softness terms.

solverIterations int

The number of solver iterations to execute.

relaxationIterations int

The number of relaxation iterations to execute after solving.

multiThread bool

If true, uses the internal thread pool for parallel execution. Multithreaded calls are internally serialized across all worlds because the worker pool is process-wide.

Remarks

Useful after restoring a saved scene, before resuming Step(float, bool). Only active contacts and constraints are solved. No new collisions are detected, forces are not applied, and positions and orientations are left unchanged.

Exceptions

ArgumentException

Thrown if dt is negative or not finite, solverIterations is less than 1, or relaxationIterations is negative.

Step(float, bool)

Performs a single simulation step.

public void Step(float dt, bool multiThread = true)

Parameters

dt float

The duration of time to simulate in seconds. Should remain fixed and not exceed 1/60 s.

multiThread bool

If true, uses the internal thread pool for parallel execution. Set to false for single-threaded execution (useful for debugging or platforms without threading).

Remarks

The step is divided into SubstepCount substeps for improved stability. Do not step or modify this world from another thread while this call is running. Multithreaded steps in different worlds wait for each other; single-threaded steps can run concurrently. Step and substep events run on the calling thread. Collision filters may run concurrently on worker threads when multiThread is true.

Exceptions

ArgumentException

Thrown if dt is negative or not finite.

Trim()

Reduces excess capacity in internal world storage.

public void Trim()

Remarks

Use this after removing many objects to release unused collection capacity. Existing bodies, constraints, contacts, and arbiters remain valid. Unmanaged simulation buffers are not compacted.

Do not use or modify this world from other threads while trimming, including queries through DynamicTree.

Exceptions

ObjectDisposedException

Thrown if this world has been disposed.

TryLockTwoBody(ref RigidBodyData, ref RigidBodyData)

Attempts to lock two rigid bodies. Briefly waits on contention, then backs off if unsuccessful. The lock order is determined by memory address to prevent deadlocks.

public static bool TryLockTwoBody(ref RigidBodyData b1, ref RigidBodyData b2)

Parameters

b1 RigidBodyData

Reference to the first rigid body data.

b2 RigidBodyData

Reference to the second rigid body data.

Returns

bool

true if both locks were acquired; otherwise, false.

UnlockTwoBody(ref RigidBodyData, ref RigidBodyData)

public static void UnlockTwoBody(ref RigidBodyData b1, ref RigidBodyData b2)

Parameters

b1 RigidBodyData

Reference to the first rigid body data.

b2 RigidBodyData

Reference to the second rigid body data.

Events

ConstraintRemoved

Raised after a constraint has been permanently removed from the world.

[CallbackThread(ThreadContext.MainThread)]
public event Action<Constraint>? ConstraintRemoved

Event Type

Action<Constraint>

Remarks

The event is raised for explicit removal as well as automatic removal caused by removing a body or clearing the world. It is not raised when a constraint is disabled, when a body's motion type changes, or when the world is disposed. The constraint is invalid when the callback runs, but its Body1 and Body2 references remain available.

IslandActivated

Raised when a group of connected bodies wakes up.

[CallbackThread(ThreadContext.MainThread)]
public event Action<Island>? IslandActivated

Event Type

Action<Island>

Remarks

The bodies are already awake when this callback runs. Islands can split, merge, or be reused, so copy any data you need instead of retaining the island reference. Do not add or remove bodies, shapes, constraints, or contacts, or change body motion types in this callback.

IslandDeactivated

Raised when a group of connected bodies goes to sleep.

[CallbackThread(ThreadContext.MainThread)]
public event Action<Island>? IslandDeactivated

Event Type

Action<Island>

Remarks

The bodies are already asleep when this callback runs. Islands can split, merge, or be reused, so copy any data you need instead of retaining the island reference. Do not add or remove bodies, shapes, constraints, or contacts, or change body motion types in this callback.

PostStep

Raised at the end of a simulation step, after all substeps, collision handling, and integration have completed.

[CallbackThread(ThreadContext.MainThread)]
public event World.WorldStep? PostStep

Event Type

World.WorldStep

Remarks

Body states contain the completed step's results. This event runs once per call to Step(float, bool), on the calling thread.

PostSubStep

Raised at the end of each substep during a simulation step.

[CallbackThread(ThreadContext.MainThread)]
public event World.WorldStep? PostSubStep

Event Type

World.WorldStep

Remarks

Runs on the calling thread, after bodies have moved and constraints have been solved. Do not add or remove bodies, shapes, constraints, or contacts, or change body motion types in this callback.

PreStep

Raised at the beginning of a simulation step, before any collision detection, constraint solving, or integration is performed.

[CallbackThread(ThreadContext.MainThread)]
public event World.WorldStep? PreStep

Event Type

World.WorldStep

Remarks

Use this event to apply forces or update bodies before the simulation advances. It runs once per call to Step(float, bool), on the calling thread.

PreSubStep

Raised at the beginning of each substep during a simulation step.

[CallbackThread(ThreadContext.MainThread)]
public event World.WorldStep? PreSubStep

Event Type

World.WorldStep

Remarks

Runs on the calling thread, before forces are applied and constraints are solved. Do not add or remove bodies, shapes, constraints, or contacts, or change body motion types in this callback.