Walkable dioramas with Jolt: capsules, ramps and gameplay shapes
Moving from bounding boxes to real 3D collision with Jolt Physics, and the two rules that made it simple.
The first diorama scenes had no real 3D collision. The player walked on a stand-in that asked every mesh for the top of its bounding box. That works for boxes and terraces, but not for a curved bridge, a slope or a cave floor, and the new art direction was full of all three.
So Hydro now uses Jolt Physics for 3D, behind the same physics subsystem as Box2D. Box2D stays for 2D games.
Rule 1: the gameplay shape is not the visual shape
What you see and what you walk on are designed separately:
- Stairs: steps to look at, a ramp to walk on.
- A torii gate: two pillar colliders, nothing for the roof.
- A tree: a trunk collider and an occluder.
Built-in shapes collide as exactly what they are: a box as a box, stairs as a ramp. Imported models collide only through dedicated nodes in the model file: _COL for solid convex shapes, _WALK for walkable triangles. These are never drawn. The render mesh never becomes collision by accident.
Rule 2: the capsule is the character
Hair, sleeves, weapons and animation frames never change collision. Every character is a Jolt CharacterVirtual: a capsule standing on the entity's position, which is also where the sprite's feet are. It:
- slides along walls,
- walks slopes up to a maximum angle,
- steps up and down small heights, like stair edges,
- sticks to the ground when walking downhill,
- and optionally never walks off a ledge.
How scripts drive it
A script never moves a character directly. In the update stage it says where the character wants to go, CharacterBody::Move(entity, velocity), and the physics stage does the rest at a fixed 60 Hz (at most four steps a frame, so a hitch can't spiral). The result is written back to the transform and interpolated between steps, so movement stays smooth on high refresh-rate displays.
All Jolt state lives in a per-scene PhysicsScene3D, never in components, following Hydro's rules for runtime state. Play mode builds it, Stop destroys it, and nothing leaks between runs.
What's still to do
No rigid bodies or joints yet, and characters don't collide with each other. The next steps are curved bridges and caves built from _WALK nodes, NPCs on character bodies, and fading out scenery that hides the player.