How to Load GLTF Animations as Separate Files in Three.js
March 16, 2022
Recently, I have been experimenting a bit with applying Mixamo motion captures to GLTF files loaded via Three.js. I reached a point however, where for convenience sake I wanted to be able to load the animation tracks as separate files, rather than having all the animations combined with the model in one GLTF / GLB file. For me this meant that I could simply download and add new animations to the model as required.
At the time of writing this article there were some notes available for this online however I found them to be a bit hard to wrap my head around.
Above is a relatively simple interactive demo in which the animations are loaded as separate GLB files using Three.js.
You’re probably best to open the demo and check out the source code, and if you’re generally familiar with Three.js and loading files etc, hopefully this code will all be fairly straightforward to you. The main thing is that I have created an array which I called ‘actions’ and every time I load an animation I simply push it into this array.
Quick disclaimer, even though I do heaps of work with code, I do not regard myself as a top level coder. (- I’m more of a front end kind of guy). So please keep me posted if you find issues with this code and or if you can offer me any suggestions for how to improve it. 😉
I should also probably mention that in my demo I included the Idle animation with the model as it seemed to work best to have a ‘default’ animation included with the model. I’m also in the habit of including my mixers in an array of mixers just so things are in place for scenes which require multiple mixers.
Otherwise here is an extract of the code showing the main functions for loading the model and the animations.
// Load GLTF
const gltf_loader = new GLTFLoader();
gltf_loader.load(
'./_glb/robot-idle.glb', function ( gltf ) {
console.log( "Robot model with idle animation loaded" );
const model = gltf.scene;
mixer_1 = new THREE.AnimationMixer( model );
mixers.push( mixer_1 );
action_1 = mixer_1.clipAction( gltf.animations[0]);
actions.push(action_1);
action_1.play();
currentAction = mixer_1.clipAction(gltf.animations[0]);
scene.add(model);
load_animations();
}
);
function load_animations() {
gltf_loader.load(
'./_glb/look-around.glb', function ( gltf ) {
console.log( "Look Around animation loaded" );
action_2 = mixer_1.clipAction(gltf.animations[0]);
actions.push(action_2);
}
);
// ...
In this example my animation blending is fairly basic and maybe a bit clumsy, but for the most part it seems to work. – I’m looking forward to developing a more advanced system for this to allow specific animations to finish before they are interrupted by the new animation etc. – You would need this for something like a jump animation.
At some point I’m also aiming to update this demo so the UI is not visible and accessible until the model and all the animations are loaded. – I realise this is a bit of a bug but in this case the robot and animation files are relatively small, so I’m not super worried about this just now.
If by chance you’re interested in the Robot model that I have used here, I made this available as a free resource Blender file which you can find over in my resources section.
Recently I have also been developing my own third person player controller system for Three.js. If by chance you’re interested, you can check out them demo here, and learn more about the project here. Here’s a screen-shot from the demo.

I would love to make it my thing to create tutorials and learning resources that are 100% free with no strings attached.
If this tutorial was useful for you please consider showing your appreciation and offering your support. It will make my day!
Buy me a coffee