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
BroadPhaseFilter
A filter that can reject shape pairs before testing them for collisions. Default is null.
public IBroadPhaseFilter? BroadPhaseFilter { get; set; }
Property Value
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
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
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
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
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
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
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
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
IsDisposed
Gets a value indicating whether this world has been disposed.
public bool IsDisposed { get; }
Property Value
Islands
All collision islands in this world.
public ReadOnlyPartitionedSet<Island> Islands { get; }
Property Value
NarrowPhaseFilter
A filter that can reject collisions or adjust contact points and normals. Defaults to TriangleEdgeCollisionFilter.
public INarrowPhaseFilter? NarrowPhaseFilter { get; set; }
Property Value
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
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
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
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
SolveMode
The solver strategy used during Step(float, bool). Defaults to Regular.
public SolveMode SolveMode { get; set; }
Property Value
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
solveris less than 1 orrelaxationis 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
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
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
body1RigidBodyThe first rigid body involved in the constraint.
body2RigidBodyThe second rigid body involved in the constraint.
Returns
- T
A new instance of the specified constraint type, already registered with the world.
Type Parameters
TThe specific type of constraint to create.
Exceptions
- ArgumentException
Thrown if either body does not belong to this world.
- SameBodyException
Thrown if
body1andbody2are 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
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
proxyAIDynamicTreeProxyproxyBIDynamicTreeProxy
Returns
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
islandIslandThe 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
islandis null.- ArgumentException
Thrown if
islanddoes 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
id0ulongThe first identifier (e.g., shape ID).
id1ulongThe second identifier.
arbiterArbiterThe arbiter for the ordered ID pair, or null if none exists.
Returns
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
id0ulongThe first identifier associated with the contact (e.g., shape or feature ID).
id1ulongThe second identifier associated with the contact.
body1RigidBodyThe first rigid body. Used only if a new arbiter is created.
body2RigidBodyThe second rigid body. Used only if a new arbiter is created.
arbiterArbiterThe 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
b1RigidBodyDataReference to the first rigid body data.
b2RigidBodyDataReference 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
arbiterArbiterThe existing Arbiter instance to which the contact will be added.
point1JVectorThe contact point on the first body, in world space.
point2JVectorThe contact point on the second body, in world space.
normalJVectorThe contact normal, in world space. Must be a unit vector pointing from the arbiter's first body toward its second body.
removeFlagsContactData.SolveModeA 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
id0ulongThe first identifier associated with the contact (e.g., shape or feature ID).
id1ulongThe second identifier associated with the contact.
body1RigidBodyThe first rigid body involved in the contact.
body2RigidBodyThe second rigid body involved in the contact.
normalJVectorThe contact normal, in world space. Must be a unit vector pointing from
body1towardbody2.manifoldCollisionManifoldA CollisionManifold containing contact point pairs in world space.
removeFlagsContactData.SolveModeA 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
id0ulongThe first identifier associated with the contact (e.g., shape or feature ID).
id1ulongThe second identifier associated with the contact.
body1RigidBodyThe first rigid body involved in the contact.
body2RigidBodyThe second rigid body involved in the contact.
point1JVectorThe contact point on
body1, in world space.point2JVectorThe contact point on
body2, in world space.normalJVectorThe contact normal, in world space. Must be a unit vector pointing from
body1towardbody2.removeFlagsContactData.SolveModeA 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
arbiterArbiterThe arbiter to remove.
Exceptions
- ArgumentNullException
Thrown if
arbiteris null.- ArgumentException
Thrown if
arbiterdoes 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
constraintConstraintThe constraint to be removed.
Exceptions
- ArgumentNullException
Thrown if
constraintis null.- ArgumentException
Thrown if
constraintdoes 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
bodyRigidBodyThe rigid body to remove.
Exceptions
- ArgumentNullException
Thrown if
bodyis null.- ArgumentException
Thrown if
bodydoes not belong to this world.- InvalidOperationException
Thrown if
bodyhas 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
countintThe 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
dtfloatThe reference timestep in seconds used to scale bias and softness terms.
solverIterationsintThe number of solver iterations to execute.
relaxationIterationsintThe number of relaxation iterations to execute after solving.
multiThreadboolIf 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
dtis negative or not finite,solverIterationsis less than 1, orrelaxationIterationsis negative.
Step(float, bool)
Performs a single simulation step.
public void Step(float dt, bool multiThread = true)
Parameters
dtfloatThe duration of time to simulate in seconds. Should remain fixed and not exceed 1/60 s.
multiThreadboolIf 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
dtis 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
b1RigidBodyDataReference to the first rigid body data.
b2RigidBodyDataReference to the second rigid body data.
Returns
UnlockTwoBody(ref RigidBodyData, ref RigidBodyData)
Releases locks on two rigid bodies previously acquired by LockTwoBody(ref RigidBodyData, ref RigidBodyData) or TryLockTwoBody(ref RigidBodyData, ref RigidBodyData).
public static void UnlockTwoBody(ref RigidBodyData b1, ref RigidBodyData b2)
Parameters
b1RigidBodyDataReference to the first rigid body data.
b2RigidBodyDataReference 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
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
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
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
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
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
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
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.