Move a rig.
Blend every layer.
Glint preserves glTF node hierarchy and skins, evaluates animation in Dart, and feeds static or mixed poses directly to GPU skinning.
Load the preserved rig
final rig = await GlintGlbRig.fromAsset(
'assets/models/character.glb',
);
final animation = GlintAnimationController(
rig,
initialAnimation: 0,
);GlintGlbRig keeps local meshes, nodes, skins, inverse bind matrices, and clips together. The renderer validates skin indices, joint references, finite matrices, and its per-skin joint limit before drawing.
Advance and render a pose
final frame = animation.update(dt);
return GlintGameInstance(
model: 'character',
animationPose: frame.pose,
transform: characterTransform,
);When animationPose is present it takes precedence over raw clip index/time fields. Sampling supports LINEAR, STEP, and glTF CUBICSPLINE channels.
animation.play(
animation.animationIndexByName('Run'),
fadeDuration: .25,
restart: false,
);An interrupted crossfade begins from the currently visible mixed pose, avoiding a pop back to either source clip.
Layer only the bones you need
final upperBody = GlintBoneMask.fromNodeNames(
rig,
['Spine'],
includeDescendants: true,
);
animation.addLayer(GlintAnimationLayer(
name: 'aim',
animationIndex: aimClip,
mask: upperBody,
weight: .8,
));Override layers blend toward a clip. Additive layers apply a delta from a reference time, useful for recoil, lean, breathing, and facial motion. Timeline events report every marker crossed, including loops and reverse playback.
Extract root motion once
Configure a skeleton root and let the controller return translation and rotation deltas. Apply those deltas to the entity or physics motor; optionally remove them from the rendered pose so motion is not doubled.
final controller = GlintAnimationController(
rig,
initialAnimation: runClip,
rootMotionOptions: const GlintRootMotionOptions(
nodeIndex: 3,
removeFromPose: true,
),
);
final frame = controller.update(fixedDt);
character.applyRootMotion(frame.rootMotion);Drive animation with state
GlintAnimationStateMachine coordinates parameter-driven transitions, one-shots, and return behavior on top of the same controller. Keep gameplay authority outside the animation graph: the state machine decides presentation, not collision or game rules.
CrossfadesSmooth base-clip changes with interruption safety.
One-shotsActions such as hit, reload, or celebrate that can return to locomotion.
Bone masksRestrict an override or additive layer to named branches.
EventsTrigger footsteps, impacts, particles, and audio at authored timeline times.
Blend animation and ragdoll physics
A GlintRagdollDefinition maps arbitrary node names or indices to colliders and fixed, revolute, or spherical constraints. It works for humanoids, animals, robots, or a partial simulated appendage.
final ragdoll = GlintRagdoll.create(
world: physics,
rig: rig,
pose: animation.pose,
simulated: false,
definition: definition,
);
ragdoll.driveFromAnimation(animation.pose);
ragdoll.setSimulated(true, linearVelocity: character.velocity);
ragdoll.applyImpulse('chest', impactImpulse);
final renderPose = ragdoll.poseFromPhysics(
animation.pose,
weight: ragdollBlend,
);Kinematic mode follows animation. Dynamic mode lets the backend solve the articulated bodies. Pose blending preserves unmapped nodes, so face, accessory, and partial-body animation can continue.