mcpField
T
threejs-animation

threejs-animation

github.com/akillnessDevelopment5356 installsUpdated today
Repository

About threejs-animation

A Three.js skill for implementing animation in 3D scenes, aimed at developers working with imported clips, rigs, and procedural motion. It emphasizes delta-time updates, deliberate transitions, and cleanup tied to the model lifecycle.

Key features

  1. 01Manage clips with AnimationMixer
  2. 02Blend and transition animation actions
  3. 03Drive bones and morph targets
  4. 04Use delta time for frame-independent motion
  5. 05Clean up mixer state and listeners

Use cases

  1. 01Play, pause, seek, or loop imported clips
  2. 02Fix frame-rate-dependent animation
  3. 03Blend actions without visual snapping
  4. 04Avoid retained animation state after scene removal

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/akillness/jeo-skills --skill threejs-animation

After installing, type/threejs-animationin Claude Code to confirm it loaded.

Bundled filesSKILL.toonevals/evals.json

Details

From the project README

Three.js Animation

Use this skill for the animation implementation itself: clip selection, mixer ownership, blending, skeleton/morph driving, and time-step correctness. Use threejs-loaders to load the model and web-game-development when game-state or combat design—not the animation API—is the primary problem.

When to use this skill

  • Play, pause, seek, loop, or blend AnimationClip data through AnimationMixer
  • Attach GLTF clips to a loaded scene and clean mixers up with the model lifecycle
  • Animate skeletal bones, morph target influences, or lightweight procedural movement
  • Fix actions that do not play, snap during transitions, speed up with frame rate, or leak

Instructions

Step 1: Identify the animation owner and clock
  1. Inspect the model's gltf.animations, root object, and current render-loop owner.
  2. Create one mixer per animated root and advance it once per frame with elapsed delta time, not a fixed per-frame amount.
  3. Preserve action references by semantic name; do not index an exported clip array blindly because asset revisions can reorder clips.
const mixer = new THREE.AnimationMixer(gltf.scene);
const clips = new Map(gltf.animations.map((clip) => [clip.name, clip]));
const idle = mixer.clipAction(clips.get("Idle"));
idle.reset().fadeIn(0.2).play();

const clock = new THREE.Clock();
function update() {
  mixer.update(clock.getDelta());
  renderer.render(scene, camera);
  requestAnimationFrame(update);
}
update();
Step 2: Transition actions without visual discontinuities

Set loop and clamp behavior deliberately, reset an incoming action before playing it, and use cross-fades only when clips share a compatible pose/rig.

function transition(from, to, duration = 0.2) {
  to.reset().setEffectiveWeight(1).setEffectiveTimeScale(1).play();
  from.crossFadeTo(to, duration, false);
}

For one-shot actions, listen for the mixer's finished event and transition back to a known idle action. Remove listeners during feature teardown.

Step 3: Choose the narrowest animation mechanism
NeedDefault mechanism
Authored transform/property keysAnimationClip + keyframe tracks
Imported character animationAnimationMixer + clipAction
Per-frame idle motion or UI responseDelta-time procedural update
Facial expressions or mesh deformationmorphTargetInfluences
Runtime bone adjustmentBone transform after mixer update
Layered additive poseAdditive clip only after validating reference pose

Apply procedural bone offsets after mixer.update(delta) so the authored clip does not overwrite them. Keep expensive IK, physics, or retargeting behind a measured budget.

Step 4: Dispose animation state with the feature

Call mixer.stopAllAction() and mixer.uncacheRoot(root) when the animated root is permanently removed. Do not uncache a root shared by another scene or instance.

Step 5: Verify animation behavior
  • Test at a low and high frame rate; duration and travel must remain consistent.
  • Test transition interruption, one-shot completion, and rapid action changes.
  • Confirm named clips exist and report a useful error when an expected asset export changes.
  • Verify cleanup by mounting/unmounting the scene repeatedly without growing listeners or retained mixer actions.

Examples

Animate a morph target
const face = gltf.scene.getObjectByName("Face");
face.morphTargetInfluences[0] = 0.75;

Validate that the mesh has morph targets and use a named index map from the asset rather than a magic number when the export includes multiple expressions.

Drive a simple procedural bob
const elapsed = clock.getElapsedTime();
mesh.position.y = baseY + Math.sin(elapsed * 2) * 0.1;

Store baseY separately. Incremental position changes accumulate drift and make mixing with authored animation difficult.

Best practices

  1. Update mixers exactly once per frame with delta seconds.
  2. Prefer exported clips for authored movement; procedural offsets should be additive and localized.
  3. Name clips at export time and validate names at load time.
  4. Avoid cloning a rig or mixer without checking shared skeleton and material ownership.
  5. Profile skinned meshes and morph targets on target hardware before multiplying them.

References

Comments

Markdown supported