2.7 · Physics (Box2D)
Two-dimensional rigid-body physics for 2D gameplay — small enough that the Scene talks to Box2D directly instead of through an abstraction layer.
b2World directly. Entity components describe bodies and colliders; two TimeManager runners step the world and sync transforms.Overview
Box2D powers the engine's 2D mechanics. Unlike Jolt — which sits behind PhysicsAPI /
PhysicsScene — Box2D is consumed directly: Scene calls
CreateBox2DWorld and DestroyBox2DWorld to own a b2World, and the 2D
components own raw Box2D handles. There is no Physics2DAPI interface.
The whole 2D surface area is one world type plus three components. Adding an interface layer for a library
that's already minimal would buy nothing in exchange for double the headers and double the indirection. If a
second 2D backend ever shows up, that's the moment to introduce Physics2DAPI — not before.
Components
| Component | Wraps | Notes |
|---|---|---|
RigidBody2DComponent | b2Body* | Body type (static / kinematic / dynamic), fixed rotation flag. |
BoxCollider2DComponent | b2PolygonShape fixture | Half-extents, offset, density / friction / restitution. |
CircleCollider2DComponent | b2CircleShape fixture | Radius, offset, density / friction / restitution. |
Lifecycle & stepping
The b2World is built when the scene enters runtime and torn down on stop. Stepping happens in two
TimeManager runners:
| Runner | What it does |
|---|---|
UpdateBox2DPhysics | Calls b2World::Step(dt, vel_iters, pos_iters) — the integration step. |
Update2DPhysicsTransforms | Copies b2Body positions and angles back into entity TransformComponents. |
Note that Box2D doesn't follow the same five-phase Acquisition → Control → Physics → Validation → Export pipeline that Jolt and MuJoCo use. The 2D surface is small enough that a step-and-sync pair is sufficient.
Pitfalls
The b2Body* stored in RigidBody2DComponent belongs to the b2World, not
the registry. Don't outlive the world with one — recreate the body on scene reload.
Box2D fixtures are immutable. Editing a 2D collider at runtime means destroying and recreating the fixture on the existing body.
Box2D and Jolt step independently; they don't share contacts or transforms. Treat them as parallel worlds.
Mixing them on a single entity is supported but the two physics representations only meet in the entity's
TransformComponent.
Extending
- New 2D collider: add a component (e.g.
PolygonCollider2DComponent), serialize it, draw it inSceneHierarchyPanel, then create the matching fixture in the Box2D world setup path. - Joints: model joints as their own components and register a runner that creates / destroys
b2Jointinstances alongside the bodies. - Second backend: that's the point at which extracting a
Physics2DAPIabstraction is worth the cost. Mirror the layout of Physics (Jolt).