Skip to content

PhysicsAPI reference

Interface IPhysicsWorld2D

Namespace: MicroEngine.Physics
Assembly: MicroEngine.Physics.dll
Guide: Physics worlds

A 2D physics world: bodies owned by entities, shapes with collision layers, kinematic collide-and-slide moves, ray and overlap queries, sensors, and a step. The members below are the common contract every backend passes (one conformance suite); everything else is a declared capability (Capabilities), and a request that needs an undeclared one throws PhysicsCapabilityException without changing the world.

C#
public interface IPhysicsWorld2D

Remarks

The rules of the contract:

  1. Bodies and shapes. Static and kinematic bodies and axis-aligned box shapes are common; a shape is placed at its body's origin plus its offset. Ids are generation-checked: a stale id is never alive, and using one throws `InvalidOperationException`; destroying a body destroys its shapes.
  2. Layers. Two shapes collide only when each one's [Mask](/docs/api/microengine.physics.shapedescription/#MicroEngine_Physics_ShapeDescription_Mask) holds the other's [Category](/docs/api/microengine.physics.shapedescription/#MicroEngine_Physics_ShapeDescription_Category); a query or move sees a shape only when [Accepts](/docs/api/microengine.physics.queryfilter/#MicroEngine_Physics_QueryFilter_Accepts_System_UInt64_System_UInt64_) is true for it.
  3. Move moves a kinematic body's one non-sensor shape, an axis-aligned box (the common character shape; a capsule needs [Capsules](/docs/api/microengine.physics.physicscapabilities/)), by collide-and-slide against the non-sensor shapes the filter accepts: it never passes through a shape at the speeds the conformance suite tests, and a blocked axis stops while the others go on. It may stop short of a surface by a gap of at most [Skin](/docs/api/microengine.physics.iphysicsworld2d/#MicroEngine_Physics_IPhysicsWorld2D_Skin), the tolerance the backend declares (0 on the tile backend). The body's contacts and its ground are in the [MoveResult](/docs/api/microengine.physics.moveresult/); a shape the box already overlaps when the move starts does not block it, so a body is never trapped.
  4. Queries. [RayCast](/docs/api/microengine.physics.iphysicsworld2d/#MicroEngine_Physics_IPhysicsWorld2D_RayCast_System_Numerics_Vector2_System_Numerics_Vector2_MicroEngine_Physics_QueryFilter__MicroEngine_Physics_RayHit__) returns the closest hit; [Overlap](/docs/api/microengine.physics.iphysicsworld2d/#MicroEngine_Physics_IPhysicsWorld2D_Overlap_MicroEngine_RectF__MicroEngine_Physics_QueryFilter__System_Span_MicroEngine_Physics_ShapeId__) is exact (shapes that truly overlap the area, not their bounding boxes; sharing an edge is not overlapping). Both leave sensors out unless the filter includes them.
  5. Sensors. A sensor reports the non-sensor shapes of kinematic and dynamic bodies that begin or stop overlapping it, when the layers of both accept each other and the visitor has [SensorEvents](/docs/api/microengine.physics.shapedescription/#MicroEngine_Physics_ShapeDescription_SensorEvents) (the default). Sensors do not see other sensors or static shapes.
  6. Events are buffered per step. [Step](/docs/api/microengine.physics.iphysicsworld2d/#MicroEngine_Physics_IPhysicsWorld2D_Step_System_Single_) computes [SensorEvents](/docs/api/microengine.physics.iphysicsworld2d/#MicroEngine_Physics_IPhysicsWorld2D_SensorEvents) and [ContactEvents](/docs/api/microengine.physics.iphysicsworld2d/#MicroEngine_Physics_IPhysicsWorld2D_ContactEvents) from the poses at its end (moves made before it count in it); they stay readable until the next step, in an order that depends only on the world's history. Contact events only come from pairs with a dynamic body. Destroying a shape ends its pairs with an exit or end event at the next step.
  7. No managed callbacks during [Step](/docs/api/microengine.physics.iphysicsworld2d/#MicroEngine_Physics_IPhysicsWorld2D_Step_System_Single_). Per-shape rules (one-way platforms) are shape flags the backend implements itself; games read events after the step.
  8. Stepping. [PhysicsModule](/docs/api/microengine.physics.physicsmodule/) steps registered worlds in the kernel's FramePhase.Physics, inside the fixed step, and writes body poses to their owners' transforms; the scene world interpolates them for drawing.
  9. Determinism. The same backend build gives identical results on every target for the same calls (native backends are built with floating-point contraction off and step on one thread). Nothing is promised between two backends, or between two versions of a backend's physics library: they differ from the first step.

A world is not thread-safe.

Properties

Backend

The backend’s name, for messages (“tiles”, “box2d”).

C#
string Backend { get; }

Property Value

string

Bodies

The live bodies, in creation order (a destroyed body leaves its place).

C#
ReadOnlySpan<BodyId> Bodies { get; }

Property Value

ReadOnlySpan<BodyId>

Capabilities

What the backend offers beyond the common contract.

C#
PhysicsCapabilities Capabilities { get; }

Property Value

PhysicsCapabilities

ContactEvents

The contacts that began or ended in the latest step (pairs with a dynamic body only).

C#
ReadOnlySpan<ContactEvent> ContactEvents { get; }

Property Value

ReadOnlySpan<ContactEvent>

SensorEvents

The sensor entries and exits of the latest step.

C#
ReadOnlySpan<SensorEvent> SensorEvents { get; }

Property Value

ReadOnlySpan<SensorEvent>

Skin

The largest gap Move may leave between a body and the surface that stopped it or that it rests on, in world units: 0 when resting is exact.

C#
float Skin { get; }

Property Value

float

StepCount

How many times Step ran.

C#
long StepCount { get; }

Property Value

long

Up

The world’s up direction (unit length): it tells ground from ceilings and which side of a one-way platform stops bodies.

C#
Vector2 Up { get; }

Property Value

Vector2

Methods

AddShape(BodyId, in ShapeDescription)

Attaches a shape to body.

C#
ShapeId AddShape(BodyId body, in ShapeDescription shape)

Parameters

body BodyId

shape ShapeDescription

Returns

ShapeId

Exceptions

PhysicsCapabilityException

The description needs an undeclared capability.

ArgumentException

The description is invalid (Validate).

InvalidOperationException

The body id is stale.

BodyOf(ShapeId)

The body shape is attached to.

C#
BodyId BodyOf(ShapeId shape)

Parameters

shape ShapeId

Returns

BodyId

Exceptions

InvalidOperationException

The id is stale.

CreateBody(EntityId, in BodyDescription)

Creates a body owned by owner.

C#
BodyId CreateBody(EntityId owner, in BodyDescription body)

Parameters

owner EntityId

body BodyDescription

Returns

BodyId

Exceptions

PhysicsCapabilityException

The description needs an undeclared capability.

ArgumentException

The description is invalid (Validate).

DescriptionOf(ShapeId)

The description shape was added with (its geometry is relative to its body’s origin).

C#
ShapeDescription DescriptionOf(ShapeId shape)

Parameters

shape ShapeId

Returns

ShapeDescription

Exceptions

InvalidOperationException

The id is stale.

PhysicsCapabilityException

The backend does not declare ShapeInspection.

DestroyBody(BodyId)

Destroys the body and its shapes; nothing for a stale or none id. Their sensor pairs end at the next step.

C#
void DestroyBody(BodyId body)

Parameters

body BodyId

IsAlive(BodyId)

Whether body exists.

C#
bool IsAlive(BodyId body)

Parameters

body BodyId

Returns

bool

IsAlive(ShapeId)

Whether shape exists.

C#
bool IsAlive(ShapeId shape)

Parameters

shape ShapeId

Returns

bool

KindOf(BodyId)

How body moves.

C#
BodyKind KindOf(BodyId body)

Parameters

body BodyId

Returns

BodyKind

Exceptions

InvalidOperationException

The id is stale.

Move(BodyId, Vector2, in QueryFilter)

Moves a kinematic body by delta with collide-and-slide against the shapes filter accepts (see the rules); a body that pushes bodies (PushesBodies) is not blocked and moves the bodies in its way instead.

C#
MoveResult Move(BodyId body, Vector2 delta, in QueryFilter filter = default)

Parameters

body BodyId

delta Vector2

filter QueryFilter

Returns

MoveResult

Exceptions

InvalidOperationException

The id is stale, the body is not kinematic, or it has no single non-sensor shape the backend can move.

ArgumentOutOfRangeException

delta is not finite.

Overlap(in RectF, in QueryFilter, Span<ShapeId>)

Writes into results the shapes that truly overlap area, in an order that depends only on the world’s history, and returns how many overlap (which may exceed the span’s length: only the first ones are written).

C#
int Overlap(in RectF area, in QueryFilter filter, Span<ShapeId> results)

Parameters

area RectF

filter QueryFilter

results Span<ShapeId>

Returns

int

OwnerOf(BodyId)

The entity that owns body.

C#
EntityId OwnerOf(BodyId body)

Parameters

body BodyId

Returns

EntityId

Exceptions

InvalidOperationException

The id is stale.

PositionOf(BodyId)

The body’s origin.

C#
Vector2 PositionOf(BodyId body)

Parameters

body BodyId

Returns

Vector2

Exceptions

InvalidOperationException

The id is stale.

RayCast(Vector2, Vector2, in QueryFilter, out RayHit)

The closest shape the segment from from to to enters; a shape holding from is not hit.

C#
bool RayCast(Vector2 from, Vector2 to, in QueryFilter filter, out RayHit hit)

Parameters

from Vector2

to Vector2

filter QueryFilter

hit RayHit

Returns

bool

Exceptions

ArgumentOutOfRangeException

A point is not finite.

RemoveShape(ShapeId)

Removes a shape; nothing for a stale or none id. Its sensor pairs end at the next step.

C#
void RemoveShape(ShapeId shape)

Parameters

shape ShapeId

RotationOf(BodyId)

The body’s angle in radians (0 for backends without Rotation).

C#
float RotationOf(BodyId body)

Parameters

body BodyId

Returns

float

Exceptions

InvalidOperationException

The id is stale.

SetPosition(BodyId, Vector2)

Teleports the body: no collision, no pushing; sensor events follow at the next step.

C#
void SetPosition(BodyId body, Vector2 position)

Parameters

body BodyId

position Vector2

Exceptions

InvalidOperationException

The id is stale.

ArgumentOutOfRangeException

The position is not finite.

SetVelocity(BodyId, Vector2)

Sets a dynamic body’s velocity.

C#
void SetVelocity(BodyId body, Vector2 velocity)

Parameters

body BodyId

velocity Vector2

Exceptions

PhysicsCapabilityException

The backend does not declare DynamicBodies.

ShapesOf(BodyId, Span<ShapeId>)

Writes the live shapes of body, in the order they were added, into results and returns how many it has (which may exceed the span’s length: only the first ones are written).

C#
int ShapesOf(BodyId body, Span<ShapeId> results)

Parameters

body BodyId

results Span<ShapeId>

Returns

int

Exceptions

InvalidOperationException

The body is stale.

PhysicsCapabilityException

The backend does not declare ShapeInspection.

Step(float)

Advances the world by dt seconds: dynamic bodies move, and the events of this step replace the previous ones. No game code runs during it.

C#
void Step(float dt)

Parameters

dt float

Exceptions

ArgumentOutOfRangeException

dt is negative or not finite.

VelocityOf(BodyId)

A dynamic body’s velocity.

C#
Vector2 VelocityOf(BodyId body)

Parameters

body BodyId

Returns

Vector2

Exceptions

PhysicsCapabilityException

The backend does not declare DynamicBodies.