logo
Animation

movement

Animation

Free

Install with the CLI:

bjs download Animation

Animation

Maps an entity's movement speed onto a three-clip locomotion blend (idle/walk/run) with foot-slide-correcting playback.

What it does

AnimationSystem turns one number — current movement speed — into weights across three clips. Below speedThreshold the entity reads as standing still (pure idle); between walkSpeed and runSpeed it cross-fades walk into run linearly; weights then lerp toward their targets at blendSpeed per second so the blend never snaps. It also scales locomotion playback by a speedRatio clamped to [minSpeedRatio, maxSpeedRatio], which keeps feet from sliding when the character moves faster or slower than the clip was authored at (idle stays at rate 1). The System never sets the speed itself: it listens for animation.speed.set keyed by entityId, so any movement, stride, or AI producer can drive it. It emits animation.ready once the clips start, animation.state.changed the frame the dominant clip flips, and animation.blend.updated every frame with the live weights for a HUD.

Use it in a scene

A scene is just data — a list of entities, each with its components. At startup the SceneLoader turns this JSON into a live world; edit the file and reload to rebuild it.

Fastest path

bjs download scene Animation

Pulls this exact scene into your project and runs it — no copy-paste. Add --all to grab the components and assets it needs too.

Or build it from scratch with the bjs CLI:

  1. 1Scaffold a project
    npm create @babylonjsmarket/arcade@latest my-game

    World, renderer, and dev server — ready to run.

  2. 2Install dependencies
    cd my-game && npm install
  3. 3Add Animation
    bjs download Animation

    Copies its source into src/ so the scene resolves.

    First time? Run bjs login once.

  4. 4Paste the scene into src/scenes/arcade-room.ts and run
    npm run dev

    SceneLoader builds the world from the JSON; reload to rebuild.

JSON
{
  "Hero": {
    "components": {
      "Mesh": { "src": "/characters/soldier.glb" },
      "Animation": {
        "idleClip": "IDLE_RIFLE",
        "walkClip": "WALK_RIFLE",
        "runClip": "RUN_RIFLE",
        "walkSpeed": 3,
        "runSpeed": 6
      }
    }
  }
}

Props

  • idleClip (string, default "IDLE_RIFLE") — name of the idle clip in the imported GLB.
  • walkClip (string, default "WALK_RIFLE") — name of the walk clip.
  • runClip (string, default "RUN_RIFLE") — name of the run clip; falls back to pure walk if the speed never reaches the run band.
  • autoPlay (boolean, default true) — start the three clips and emit animation.ready on the entity's first frame.
  • walkSpeed (number, default 3) — movement speed at which walk weight reaches 1.
  • runSpeed (number, default 6) — movement speed at which run weight reaches 1.
  • blendSpeed (number, default 8) — weight transition rate per second; higher is snappier.
  • speedSmoothRate (number, default 4) — input-speed smoothing rate per second; higher follows the producer faster.
  • speedThreshold (number, default 0.5) — dead-zone; any speed below this reads as standing still.
  • minSpeedRatio (number, default 0.5) — lower clamp on the playback rate multiplier.
  • maxSpeedRatio (number, default 3) — upper clamp on the playback rate multiplier.

Events

  • consumes animation.speed.set{ entityId, speed }. Any producer pushes the entity's current movement speed; the matching entity blends toward it.
  • emits animation.ready{ entityId }. Fired once after the clips start playing.
  • emits animation.state.changed{ entityId, state }, where state is 'idle' | 'walk' | 'run'. Fired the frame the dominant clip flips.
  • emits animation.blend.updated{ entityId, idleWeight, walkWeight, runWeight, speedRatio }. Fired every frame, for HUDs reading the live blend.

Dependencies

meta.json lists none — the blend math is self-contained. In practice the entity also needs a rigged mesh holding the three named clips, supplied by a Mesh GLB load (the example uses idleClip/walkClip/runClip names that must exist in that GLB). Speed comes from whatever producer emits animation.speed.set — typically a movement or stride System — so Animation drops onto a player, an NPC, or any rigged mesh without knowing what moves it.

Notes

  • The clips are started once per session (guarded by an internal started set), not re-played every frame, so per-frame work is just three weight writes and two rate writes.
  • A negative dt (a replay stepping backwards) is clamped to 0, so the blend stays deterministic and never unwinds.
  • speedThreshold ≥ walkSpeed or runSpeed ≤ walkSpeed are handled as degenerate bands — the blend pins straight to walk rather than dividing by a zero-width range.
  • Removing an entity stops its three clips on the adapter and clears its cached speed, so re-adding it later starts from a clean idle.

More like this

AiPilot
AnimateMeshy
ArcCamera
Asteroid
Bullet
CameraFollow
DirectionalLight
EnemySpawner
EnvironmentTexture
FreighterCar
FreighterChain
FreighterHead
GameConfig
Health
HemisphericLight
Jump
KeyboardInput
KeyboardMover
Lifetime
LineOfSight
MachineGun
Mesh
MeshPrimitive
Missile
MissileLauncher
MissionDirector
MouseInput
Movement
Obstacle
ObstacleField
OilBlob
Parts
Physics
PlayerInput
PlayerWalkAnimator
RespawnTimer
RoundReset
Score
Shadow
ShipFlight
ShipLoadout
SkeletonAnimator
SpaceShooterBullet
SpaceShooterHealth
SpaceShooterScore
TwinStickEnemy
Velocity6DOF
WaveDirector
Waypoint
WaypointTrack

Was this page helpful?

We read every note — tell us what's working and what isn't.

↑↓ NavigateEnter SelectEsc CloseCtrl+K Open Search