FERRETGame engine over Babylon.js
Ferret

The world: entities, components, services

Skill ferret-world · download all skills · SKILL.md

When to use#

Writing a component, a service, reacting to engine events, or driving a world in a test.

The model in short#

  • World owns the scene, the clock and everything in it. Simulation runs at a fixed rate (60 Hz); world.advance(realDt) runs as many fixed steps as fit, frame time is capped (maxFrame).
  • Entity wraps a Babylon TransformNode and carries components. Component has onAttach, onStart, onFixedUpdate(dt), onUpdate(dt), onDetach.
  • Service is a world-wide singleton (world.addService, world.service(name)): input, levels, zones, physics, UI.
  • world.events is a synchronous bus: on, once, off, emit.
  • world.components / world.behaviours are Registrys: a level manifest names a class and gives plain params.

Steps for a new component#

  1. Extend Component<Params>; keep params plain data so a manifest can set it.
  2. Put game logic in onFixedUpdate, presentation in onUpdate.
  3. Register once: world.components.register('Name', Class) (see the API reference for the exact call).
  4. Find things with entity.get(Cls), require(Cls), findByName, findByTag, entitiesWith.

Time controls#

timeScale (slow motion), paused, time, tickCount, alpha (interpolation), entity.timeDilation (slow NPCs only).

Check afterwards#

Test without a renderer: drive the world with world.step() or world.run(seconds); the same inputs must give the same result.

What usually goes wrong#

  • Game logic in onUpdate: it runs per rendered frame, so results depend on frame rate.
  • Component params holding class instances: a manifest cannot express them.
  • Holding an entity reference across a level change: the level's entities are removed on unload.
  • Registering a component class twice.

Files#