Simulate more
than one genre.
The portable physics contract is the foundation. Characters, vehicles, ragdolls, destructibles, triggers, and user systems are composable consumers of it.
Add the native backend
flutter pub add glint_box3dawait GlintBox3dWorld.ensureInitialized();
final physics = GlintBox3dWorld(
gravity: const Vector3(0, -9.81, 0),
fixedTimeStep: 1 / 120,
solverSubSteps: 4,
);Game code depends on GlintPhysicsWorld, not native Box3D types. The backend supplies angular rigid bodies, sleeping, CCD, contact solving, joints, interpolation, and spatial queries.
Create bodies and colliders
final crate = physics.createBody(
const GlintRigidBodyConfig(
position: Vector3(0, 3, 0),
angularDamping: .08,
ccdEnabled: true,
),
);
crate.addCollider(
const GlintBoxCollider(Vector3(.5, .5, .5)),
material: const GlintPhysicsMaterial(
density: 80,
friction: .75,
restitution: .05,
),
collisionLayer: 1 << 2,
collisionMask: 0x7fffffff,
);Body typesStatic world geometry, dynamic solver-controlled bodies, and velocity-driven kinematic bodies.
Collider familiesSphere, box, capsule, cylinder, convex hull, triangle mesh, height field, and compound children.
MotionForces, impulses, torque, angular impulse, damping, gravity scale, axis locks, sleep, wake, and CCD.
FilteringLayers, masks, triggers, body-type inclusion, and exact excluded-body sets on queries.
Step physics at a fixed rate
GlintGameView(
models: models,
onFrame: (elapsed) {
physics.step(elapsed);
return GlintGameFrame(
camera: camera,
instances: [
GlintGameInstance(
model: 'crate',
transform: crate.toTransform(),
),
],
);
},
)step accumulates frame time, caps catch-up work, runs fixed callbacks, advances the backend, and exposes an interpolation alpha. stepFixed advances exactly one tick for tests, offline simulation, replay, and rollback.
physics.addFixedStepCallback((fixedDt) {
gameplay.applyQueuedInput(fixedDt);
});
physics.addStepCompletedCallback((stats) {
profiler.record(stats.backendTime, stats.activeContactCount);
});Query and retain contact state
The collision stream emits contact begin, fixed-tick stay, contact end, trigger enter, and trigger exit events synchronously with the simulation step. Compound shape pairs are aggregated into stable collider pairs.
physics.collisions.listen((event) {
switch (event) {
case GlintContactBegan(:final contacts):
spawnImpact(contacts);
case GlintContactStayed(:final duration):
applyContinuousEffect(duration);
case GlintTriggerEntered():
openInteractionPrompt();
default:
break;
}
});
final touchingPlayer = physics.activeContacts
.where((contact) => contact.involves(player));Use raycasts, raycast-all, sphere/box overlaps, and sphere/box shape casts for ground tests, cameras, interaction, suspension, explosions, AI perception, and custom gameplay solvers.
Move a general character
The capsule motor uses the public query contract. It handles acceleration, air control, gravity, slopes, sweep-and-slide collision, step climbing, ground snap, moving-platform velocity, jumping, and rollback state.
final character = GlintCharacterController.create(
world: physics,
position: const Vector3(0, 1, 0),
config: const GlintCharacterControllerConfig(
height: 1.8,
radius: .35,
stepHeight: .3,
slopeLimitRadians: .78,
),
);
character.desiredVelocity = moveDirection * runSpeed;
if (jumpPressed) character.jump(6);The motor does not own input mapping, camera policy, combat, or animation state. Those remain application systems, making the same controller useful in third-person games, platformers, simulations, and tools.
Compose higher-level systems
Five joint families
Fixed, revolute, prismatic, spherical, and distance constraints with limits, springs, damping, and motors where supported.
Ragdolls
Declarative rig-to-body mapping, kinematic animation drive, dynamic activation, impulses, and partial pose blending.
Raycast vehicles
Suspension, tire grip, anti-roll, dynamic surface reactions, steering, brakes, gears, aero, boost, and telemetry.
Rollback & replay
Body and participant snapshots, fixed-tick input tapes, JSON codecs, quantized state digests, and exact divergence frames.
GlintRaycastVehicle is one optional consumer of the same world. Nothing in the backend assumes cars, and omitting the vehicle layer removes all vehicle behavior.