logo

Babylon.js Market

AnimateMeshy

characters

AnimateMeshy

Listens toMesh
1
Unlock

Install with the CLI:

bjs download AnimateMeshy

AnimateMeshy

Retargets one shared animation library onto any Meshy character at runtime, and plays its clips by name.

What it does

Meshy's auto-rig gives every character the same skeleton, so their animations are interchangeable. AnimateMeshy uses that: ship each character with only an Idle baked in, keep the rest of the motion (walk, run, jump, …) in one skeleton-only animations.glb, and retarget that library onto whichever character loaded. When the sibling Mesh finishes loading (it listens for mesh.loaded), the System asks the adapter for its animateMeshy extension and calls retargetLibrary(meshId, library); the retargeted clips register under the character's id, so they play through the ordinary playAnimation(meshId, clip) path from then on. It starts the character on autoPlay (default Idle), emits animateMeshy.retargeted with the clip names, and switches clips when it hears animateMeshy.play. Swap Mesh.src to a different Meshy character and the same library still drives it.

Register the plugin once

The engine work — AnimatorAvatar on Babylon, mixer binding on Three — ships with this component as an adapter plugin, not in the framework. Register it right after you build the adapter, before the scene loads:

TypeScript
import { registerAnimateMeshyExtension } from "./AnimateMeshy/adapter/register";

const adapter = new BabylonAdapter();
registerAnimateMeshyExtension(adapter); // picks the plugin by adapter.kind
const game = new ArcadeGame(adapter, …);

Skip this and the System logs a warning and retargets nothing; the character still shows its own Idle.

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.

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 AnimateMeshy
    bjs download AnimateMeshy

    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
{
  "Player": {
    "tags": ["player"],
    "components": {
      "Mesh": { "src": "/hero/character.glb", "autoLoad": true },
      "AnimateMeshy": { "library": "/meshy-animations/animations.glb", "autoPlay": "Idle" },
      "AnimateMeshyDebugger": { "activationKey": "Digit5" },
      "Movement": { "speed": 4 },
      "KeyboardMover": {},
      "PlayerInput": {}
    }
  }
}

animations.glb is a skeleton-only clip library (~50 KB — no mesh, no textures). Serve both GLBs under public/.

Props

  • library (string) — url of the skeleton-only animations.glb retargeted onto the character on load.
  • autoPlay (string, default "Idle") — clip played once retargeting finishes.
  • panelKey (string, default "Digit5") — KeyboardEvent.code that toggles the clip-button panel.

AnimateMeshyDebugger (optional) adds the panel: visible (default true), activationKey (default Digit5), position (default top-right).

Playing clips

Emit animateMeshy.play with a clip name; the System stops the current clip and starts it. Omit entityId to target the first retargeted character.

TypeScript
eventBus.emit("animateMeshy.play", { clip: "Running", loop: true }); // { entityId?, clip, loop? }

The debugger panel does exactly this — one button per retargeted clip.

Events

  • emits animateMeshy.retargeted ({ entityId, meshId, clips }) once the library is retargeted.
  • listens for mesh.loaded (the retarget trigger), animateMeshy.play, and animateMeshy.stop.

Dependencies

Mesh — the character it retargets onto. The clips register under the mesh id, which is the entity id.

Notes

  • Retargeting is identity: every Meshy rig shares bone names, so the library binds with no name map. A source with a different skeleton would need one.
  • Each character retargets once; the guard survives the async load and a re-added entity.
  • character.glb keeps its own Idle, so the panel always offers Idle even if the library omits one.
  • The Three plugin binds donor clips onto the character's mixer, which Mesh creates only when the character glb ships at least one clip — its Idle covers that.
  • Needs a build of @babylonjsmarket/ecs that carries the adapter extension seam (registerExtension / extension).

More like this

Mesh
Animation
PlayerWalkAnimator
SkeletonAnimator

Was this page helpful?

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

↑↓ NavigateEnter SelectEsc CloseCtrl+K Open Search