Box3D Body Types Explained: Static vs Kinematic vs Dynamic Simulation Effects
Box3D defines three distinct body types—static, kinematic, and dynamic—that determine whether an entity moves under physics simulation, remains fixed as immovable scenery, or follows user-controlled motion while still affecting other bodies.
In the erincatto/box3d physics engine, every b3Body is classified by a type that fundamentally changes how it interacts with the broad-phase collision system and the constraint solver. Understanding these Box3D body types is essential for building stable simulations, from immovable level geometry to player-controlled platforms and physics-driven debris.
How Body Types Affect the Simulation Pipeline
The physics solver treats each body type differently during the integration step and collision response phase. The classification is stored internally in b3Body.type and queried through the public API at src/body.c:L1407.
Static Bodies
Static bodies represent immovable world geometry with infinite mass. They exist solely to provide collision boundaries for other objects.
- The solver never updates position or velocity
- They do not receive forces, impulses, or gravity
- Collision resolution only affects the dynamic partner in a collision pair
According to the source code in src/shape.c:L78-L80, when a shape is added to the broad-phase, its proxy type inherits the owning body’s type. For static bodies, this means they participate in collision detection but are excluded from the dynamics integration entirely.
Kinematic Bodies
Kinematic bodies bridge the gap between static and dynamic behavior. They possess infinite mass and ignore external forces, yet they generate contact constraints that push other bodies away.
- Motion is controlled directly via user-supplied velocity or position updates
- The solver treats them as proxies (
b3ProxyType) for contact generation - Impulses are never applied back to the kinematic body during collision resolution
This makes kinematic bodies ideal for moving platforms or animated objects that must affect the physics world without being affected by it.
Dynamic Bodies
Dynamic bodies are fully simulated entities with finite mass that respond to forces, torques, and collisions.
- The solver integrates linear and angular velocity each time step
- They can be put to sleep or awakened based on activity levels
- They both affect and are affected by static, kinematic, and other dynamic bodies
Dynamic bodies represent the standard physics-driven objects in your simulation, from crates to ragdolls.
API Implementation and Source Code
The body type enumeration and accessor functions are implemented in src/body.c. You can query or modify types using:
b3BodyType b3Body_GetType(b3BodyId bodyId); // src/body.c:L1407
void b3Body_SetType(b3BodyId bodyId,
b3BodyType type); // src/body.c:L1441
When shapes are created, the broad-phase proxy type is determined by the body type:
// From src/shape.c:L78-L80
proxyType = body->type;
This ensures that static bodies are handled efficiently in collision queries while kinematic bodies still generate necessary contact data. The architectural overview in docs/overview.md#L72-L90 provides additional context on these simulation roles.
Creating and Modifying Body Types
Define body types during creation using the b3BodyDef structure:
/* Static ground plane */
b3BodyDef groundDef = b3DefaultBodyDef();
groundDef.type = b3_staticBody;
b3BodyId groundId = b3CreateBody(worldId, &groundDef);
/* User-controlled platform */
b3BodyDef platformDef = b3DefaultBodyDef();
platformDef.type = b3_kinematicBody;
platformDef.position = (b3Vec3){0.0f, 5.0f, 0.0f};
b3BodyId platformId = b3CreateBody(worldId, &platformDef);
/* Physics-driven character */
b3BodyDef playerDef = b3DefaultBodyDef();
playerDef.type = b3_dynamicBody;
playerDef.position = (b3Vec3){0.0f, 1.0f, 0.0f};
b3BodyId playerId = b3CreateBody(worldId, &playerDef);
Changing Types at Runtime
You can convert bodies between types after creation. For example, freezing a dynamic object that comes to rest:
// Convert dynamic body to static to improve performance
b3Body_SetType(playerId, b3_staticBody);
This immediately updates the body’s participation in the simulation pipeline without destroying and recreating the body or its shapes.
Summary
- Static bodies provide collision geometry with zero simulation cost for movement, as the solver never integrates their transforms.
- Kinematic bodies allow scripted motion while still generating contacts that push dynamic bodies, using infinite mass to ignore external forces.
- Dynamic bodies are fully simulated with finite mass, sleeping capabilities, and complete collision response.
- The implementation distinguishes these types through
b3Body.type, accessed viab3Body_GetTypeandb3Body_SetTypeinsrc/body.c, and propagated to the broad-phase proxy system insrc/shape.c.
Frequently Asked Questions
Can I change a body type after creation without destroying the body?
Yes. Use b3Body_SetType() defined at src/body.c:L1441 to switch between static, kinematic, and dynamic modes at runtime. The change takes effect immediately in the next simulation step, updating how the broad phase and solver treat the body without requiring you to recreate collision shapes.
Why do kinematic bodies have infinite mass if they move?
Kinematic bodies use infinite mass to ensure the physics solver never applies collision impulses or forces to them. According to the Box3D source code, they act as proxies for contact generation—pushing other bodies away—while their motion remains entirely under user control via direct velocity or position updates.
Do static bodies impact simulation performance?
Static bodies have minimal performance impact because the solver skips integration for them entirely. However, they still participate in broad-phase collision detection. The src/shape.c:L78-L80 implementation ensures static shapes are tracked in the spatial hash for queries, but they generate no constraint solving overhead during the physics step.
How does the broad phase treat different body types differently?
When shapes are added to the broad phase, they inherit the proxy type from their owning body’s type field (proxyType = body->type). This determines whether the broad phase treats the shape as immovable scenery, a user-controlled object, or a fully simulated entity, optimizing collision pair generation accordingly.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →