useAnimations in React Three FiberWhen working with 3D models that include animations (like those often found in glTF/GLB files), React Three Fiber, in conjunction with @react-three/drei, provides the useAnimations hook to simplify their playback and control.
useAnimations?The useAnimations hook from @react-three/drei is designed to streamline the process of managing and playing animation clips associated with a 3D model. It abstracts away much of the boilerplate code typically required for Three.js animation mixers and actions.
useAnimationsThe typical workflow involves:
useGLTF (also from @react-three/drei). This hook provides the animations array from your model.useAnimations: You pass the animations array and a ref to the mesh or group that contains the animated model to useAnimations.actions (an object mapping animation clip names to THREE.AnimationAction instances) and mixer (the THREE.AnimationMixer instance). You can then use methods like actions[clipName].play(), actions[clipName].stop(), actions[clipName].setWeight(), etc., to control the animations.This example demonstrates how to load a glTF model with animations and play a specific animation clip using useAnimations. Note that this requires a React environment to run and a .glb model with embedded animations.
import React, { useEffect, useRef, Suspense } from 'react';
import { Canvas } from '@react-three/fiber';
import { useGLTF, useAnimations, OrbitControls } from '@react-three/drei';
function AnimatedModel(props) {
const group = useRef();
// Load the glTF model and its animations
const { scene, animations } = useGLTF(props.url);
// Get animation actions and mixer
const { actions } = useAnimations(animations, group);
useEffect(() => {
// Play a specific animation when the component mounts
// Replace 'YourAnimationName' with the actual name of an animation clip in your model
// You can inspect your glTF model in a viewer to find animation clip names.
const animationName = 'Idle'; // Common animation name, replace if needed
if (actions[animationName]) {
actions[animationName].play();
}
// Optional: Clean up animation when component unmounts
return () => {
if (actions[animationName]) {
actions[animationName].stop();
}
};
}, [actions]); // Re-run effect if actions change
return (
<group ref={group} {...props} dispose={null}>
<primitive object={scene} />
</group>
);
}
export default function App() {
return (
<Canvas camera={{ position: [0, 1, 3] }}>
<ambientLight intensity={0.5} />
<pointLight position={[10, 10, 10]} />
<Suspense fallback={null}>
<AnimatedModel url="/path/to/your_animated_model.glb" /> <!-- Replace with your model path -->
</Suspense>
<OrbitControls />
</Canvas>
);
}
group ref: The useAnimations hook needs a ref to the THREE.Object3D (usually a <group> or the <primitive> itself) that contains the animated mesh.animations array: This comes directly from the useGLTF hook.actions object: This is the most important part. It's a dictionary where keys are the names of your animation clips (as defined in your 3D software) and values are THREE.AnimationAction instances.useEffect: You'll typically use useEffect to trigger animation playback when the component mounts or when certain props/state change.useFrame (optional): For more complex animation logic or updates per frame, you might use useFrame to interact with the mixer directly, though useAnimations handles the basic mixer updates for you.