FERRETGame engine over Babylon.js
Ferret

Ferret: where to start

Skill ferret · download all skills · SKILL.md

Ferret is a game engine in a pnpm workspace of packages (@ferret/core, game, levels, character, physics-* ...). A game is a canvas, createGame, a level and game.start(). Everything the engine does is also a named command on world.commands, so a person, a test and an agent drive the same things.

Pick the skill#

TaskSkill
Install, build, first game, samplesferret-getting-started
Entities, components, services, events, the fixed stepferret-world
A level manifest, travel, environmentferret-levels
.ferret packages, signing, encryption, cachesferret-packages
Screen, device class, quality tier, saved stateferret-platform-display
Actions, bindings, touch, HUD, menusferret-input-ui
Player movement, cameraferret-character
Animation graphs, montages, retargetingferret-animation
NavMesh, NPC walking, behaviour treesferret-ai-navigation
Doors, levers, pickups, zonesferret-interaction-zones
Audio, video and web pages in the worldferret-media
Swapping one character for anotherferret-transform
Replication, backends, voice, sign-inferret-net-accounts
Building or changing a level by commandsferret-level-editor
Looking inside a running game, testsferret-debugging
A UE5 level into Ferret (plan, export, postprocess, Blueprints)ferret-unreal-porting
A ported level that looks wrong; parity with the originalferret-unreal-level-look
UE characters, NPCs, clips, Animation Blueprintsferret-unreal-characters
Anything realistic: physicsstart at ferret-physics-recipes (wish to capability), then ferret-physics-host

First steps#

  1. Read reference/getting-started.md for the build and the shape of a game.
  2. Find the skill above; open its SKILL.md, then only the reference file it points to.
  3. For an exact signature use the reference/api-<package>.md of that skill; do not guess names.

Rules that hold everywhere#

  • Game logic goes in onFixedUpdate (fixed 60 Hz step); only presentation in onUpdate. The same inputs then give the same run.
  • Bind actions, never keys; the console has a cursor, A and B and no mouse look.
  • A level's manifest refers to glTF nodes by name, so re-exports keep the wiring.
  • Everything a level builder creates is removed when the level goes; do not keep references across levels.
  • Check with the commands (world.commands.list()) and the unit tests, not by guessing.

Check afterwards#

pnpm typecheck and pnpm test pass; the sample or level loads; the commands you used answer as expected.

What usually goes wrong#

Using a key instead of an action; keeping state in a component that a level unload removes; simulating in onUpdate; naming a manifest node that the export renamed.

Files#