Skip to main content

Animations

Play VRMA animations on VRM characters. VRMA is the animation format for VRM models, supporting skeletal animation with blend shapes. The built-in @hmcs/assets MOD provides default animations.

Import

import { Vrm, repeat } from "@hmcs/sdk";

Playing Animations

vrm.playVrma(options) starts a VRMA animation on the character.

const character = await Vrm.spawn("my-mod:character");

await character.playVrma({
asset: "vrma:idle-maid",
repeat: repeat.forever(),
transitionSecs: 0.5,
});

Options

OptionTypeDefaultDescription
assetstring(required)Asset ID of the VRMA animation
repeatVrmaRepeatRepeat mode: repeat.forever(), repeat.never(), or repeat.count(n)
transitionSecsnumberCrossfade duration in seconds for blending from the current animation
waitForCompletionbooleanfalseIf true, the call blocks until the animation finishes
resetSpringBonesbooleanfalseIf true, resets spring bone velocities to prevent bouncing artifacts

Repeat Modes

The repeat namespace provides helpers for building repeat configurations:

import { repeat } from "@hmcs/sdk";

// Loop the animation indefinitely
repeat.forever();

// Play exactly once, then stop
repeat.never();

// Play exactly 3 times, then stop
repeat.count(3);
warning

repeat.count(n) requires a positive integer. Passing 0, negative numbers, or non-integers throws a RangeError.

Crossfade Transitions

Use transitionSecs to smoothly blend from the current animation into the new one. Without it, animations switch instantly.

// Smooth 0.5-second crossfade into idle
await character.playVrma({
asset: "vrma:idle-maid",
repeat: repeat.forever(),
transitionSecs: 0.5,
});

// Instant switch to grabbed animation
await character.playVrma({
asset: "vrma:grabbed",
repeat: repeat.forever(),
});

Waiting for Completion

Set waitForCompletion: true to block until a one-shot animation finishes. This is useful for sequencing animations.

// Play a wave animation and wait for it to finish
await character.playVrma({
asset: "my-mod:wave",
repeat: repeat.never(),
waitForCompletion: true,
});

// This line runs after the wave animation is done
await character.playVrma({
asset: "vrma:idle-maid",
repeat: repeat.forever(),
transitionSecs: 0.5,
});

Spring Bone Reset

When switching between animations with very different poses (e.g., standing to grabbed), spring bone physics (hair, clothing) can cause unwanted bouncing. Use resetSpringBones: true to reset velocities.

await character.playVrma({
asset: "vrma:grabbed",
repeat: repeat.forever(),
resetSpringBones: true,
});

Querying Animation State

List Active Animations

const animations = await character.listVrma();
for (const anim of animations) {
console.log(`${anim.name}: entity=${anim.entity}, playing=${anim.playing}`);
}

Check Specific Animation

const state = await character.vrmaState("vrma:idle-maid");
console.log(`Playing: ${state.playing}`);
console.log(`Speed: ${state.speed}x`);
console.log(`Elapsed: ${state.elapsedSecs}s`);
console.log(`Repeat: ${state.repeat}`);

Change Playback Speed

// Slow motion
await character.setVrmaSpeed("vrma:idle-maid", 0.5);

// Double speed
await character.setVrmaSpeed("vrma:idle-maid", 2.0);

// Normal speed
await character.setVrmaSpeed("vrma:idle-maid", 1.0);

Stop an Animation

await character.stopVrma("vrma:idle-maid");

Spring Bones

VRM models use spring bones for physics simulation on hair, clothing, and accessories. You can query and customize spring bone properties.

Query All Chains

const { chains } = await character.springBones();
for (const chain of chains) {
console.log(`Chain ${chain.entity}: ${chain.joints.length} joints`);
console.log(` Stiffness: ${chain.props.stiffness}`);
console.log(` Drag: ${chain.props.dragForce}`);
}

Modify Physics

const { chains } = await character.springBones();
const hairChain = chains[0];

// Make hair bouncier
await character.setSpringBone(hairChain.entity, {
stiffness: 0.5,
dragForce: 0.2,
});

// Change gravity direction
await character.setSpringBone(hairChain.entity, {
gravityPower: 1.0,
gravityDir: [0, -1, 0],
});

Built-in Animations

The @hmcs/assets MOD provides these default VRMA animations:

Asset IDDescription
vrma:idle-maidStanding idle animation (looping)
vrma:grabbedPicked-up/grabbed pose (looping)
vrma:idle-sittingSitting idle animation (looping)

Types

interface VrmaPlayRequest {
asset: string;
transitionSecs?: number;
repeat?: VrmaRepeat;
waitForCompletion?: boolean;
resetSpringBones?: boolean;
}

interface VrmaRepeat {
type: "forever" | "never" | "count";
count?: number;
}

interface VrmaState {
playing: boolean;
repeat: string;
speed: number;
elapsedSecs: number;
}

interface VrmaInfo {
entity: number;
name: string;
playing: boolean;
}

interface SpringBoneProps {
stiffness: number;
dragForce: number;
gravityPower: number;
gravityDir: [number, number, number];
hitRadius: number;
}

interface SpringBoneChain {
entity: number;
joints: string[];
props: SpringBoneProps;
}

Next Steps

  • Expressions -- Layer facial expressions on top of animations.
  • Events -- React to vrma-play and vrma-finish events.
  • VRM Overview -- Full API reference table.