three.js renders. GAMA makes it a game.
Steering agents · flocking · navmesh pathfinding · behavior trees ·
cameras · input · collisions · tweens · optional rapier physics & React bindings
npm install gama3d three
Composable steering: seek, flee, arrive, pursue, evade, wander, flocking, path-following, obstacle avoidance — weighted and swappable at runtime.
A* + funnel pathfinding over triangle meshes — hand-authored or baked straight from your level geometry with slope, step and agent-radius rules.
Reactive behavior trees with interruption built in, plus finite state machines for simple modal logic. Actions swap steering behaviors; conditions read the world.
Variable + fixed timestep, entities that are Object3Ds, typed events, object pooling, and safe mid-frame destruction.
Keyboard/gamepad input with named rebindable actions, character controllers, and follow/orbit/shoulder cameras with smoothing and occlusion.
A rapier adapter (rigid bodies + a stair-climbing character controller) and react-three-fiber bindings — separate entry points, zero cost if unused.
Velocity and steering-force arrows on every agent, collider wireframes, and an FPS/entity/draw-call panel. Steering bugs stop being invisible.
A level file is placements, not geometry — so it round-trips exactly, keeps kinds your build has never heard of, and loads by running your factories again. The editor on top is a real one: palette, inspector, grid snapping and undo.
Zero dependencies beyond three. A GameObject is a THREE.Object3D — the whole three.js ecosystem works unchanged.
import { Game, MotionAgent, Seek, CharacterController, FollowCamera } from 'gama3d';
const game = new Game();
const player = game.world.spawn('player');
player.addComponent(new CharacterController(game.input, { speed: 8 }));
const enemy = game.world.spawn('enemy');
enemy.position.set(10, 0, 10);
enemy.addComponent(new MotionAgent({ maxSpeed: 5, planar: true }))
.addBehavior(new Seek(player.position));
game.start();