Gltf multiple animations not starting

Hi, i’m loading a gltf file with 3 animations, but only the last animation is starting. this is my code:

<script async src="https://unpkg.com/es-module-shims@1.3.6/dist/es-module-shims.js"></script>

<script type="importmap">
  {
    "imports": {
      "three": "https://unpkg.com/three@0.143.0/build/three.module.js"
    }
  }
</script>

<script type="module">
	import * as THREE from 'three';
		
	import { GLTFLoader } from 'https://unpkg.com/three@0.143.0/examples/jsm/loaders/GLTFLoader.js';
	//import { OrbitControls } from 'https://unpkg.com/three@0.143.0/examples/jsm/controls/OrbitControls.js';
	import { RGBELoader } from 'https://unpkg.com/three@0.143.0/examples/jsm/loaders/RGBELoader.js';
	//import Stats from 'three/examples/jsm/libs/stats.module'
	
	var clock = new THREE.Clock();
	var camera, scene, renderer, mixer;
	
	function init() {
		
		scene = new THREE.Scene();
		
		const light = new THREE.PointLight( 0xffffff, 50, 150 );
		light.position.set( 10, 20, -5 );
		light.shadow.camera.top = 2000;
		light.shadow.camera.bottom = - 2000;
		light.shadow.camera.left = - 2000;
		light.shadow.camera.right = 2000;
		light.shadow.camera.near = 1;
		light.shadow.camera.far = 2000;
		light.castShadow = true;
	
		scene.add( light );
				
		camera = new THREE.PerspectiveCamera( 25, window.innerWidth / window.innerHeight, 1, 1000 );
		camera.position.set(1, 5, -40);
		camera.lookAt(new THREE.Vector3(1, 8, 1));
		
		renderer = new THREE.WebGLRenderer();
		renderer.setClearColor( 0xffffff );
		renderer.physicallyCorrectLights = true;
		renderer.shadowMap.enabled = true;
		renderer.outputEncoding = THREE.sRGBEncoding
		renderer.setSize(window.innerWidth, window.innerHeight);
		document.body.appendChild(renderer.domElement);
		
		const loader = new GLTFLoader();
		loader.load(
		    './soul3d_7.glb',
		    function (gltf) {

		             mixer = new THREE.AnimationMixer( gltf.scene );

			     gltf.animations.forEach( ( clip ) => {

			      let animation = mixer.clipAction( clip );
			    
			      animation.setLoop(THREE.LoopOnce);
	  				animation.clampWhenFinished = true;
	  				animation.enable = true;
	  				animation.play();
			          
			     } );
			     	        
		        scene.add(gltf.scene);
		    },
		    (xhr) => {
		        console.log((xhr.loaded / xhr.total) * 100 + '% loaded');
		    },
		    (error) => {
		        console.log(error);
		    }
		);
	}
	
	window.addEventListener('resize', onWindowResize, false);
	function onWindowResize() {
	    camera.aspect = window.innerWidth / window.innerHeight;
	    camera.updateProjectionMatrix();
	    renderer.setSize(window.innerWidth, window.innerHeight);
	    render();
	}
	
	function animate() {
	    requestAnimationFrame(animate);

	    if (mixer) {
		    mixer.update(clock.getDelta());
            }
	
	    render();
	
	}
	
	function render() {
	    renderer.render(scene, camera);
	}
	
	init();
	animate();
	
</script>

Can you please help me?
G

I think its because your redeclaring you animation ever loop interation using let. Thats why only the third animation works. Maybe you can loop and push to an array after you use the .play method

You can also push to an array and play them later after your imports in complete

Hi Chris, thanks for your reply.
I changed the animation loop in this way, but it is still not working:

gltf.animations.forEach( ( clip ) => {
			     	
   mixer.clipAction( clip ).play();
   anarray.push(mixer.clipAction( clip )); 
        
 } );      

I didn’t work with AnimationMixer at all in Three.js, but if it’s about video clips, there are some gotchas there. Anyway, regarding your specific question, some ideas:

  • the Three.js manual says that “when multiple objects in the scene are animated independently, one AnimationMixer may be used for each object”, so, if I understand this correctly, maybe you need to create 3 mixers, one for each animation
  • as it is now, the onload event of the loader is running once, and starting to play “each” (or not, see above) clip in quick succession; maybe it would be more effective to wait until everything is completely added to the scene and such, and only then to start playing (or create the mixer and handle animations)… well, at least that’s what I’d do, but I could be wrong
  • in case this is about video clips (more or less), they go through a succession of events until they can be played (the key event being named canplay as well); in case it’s not or this / the buffering after the xhr is handled already by Three.js, this point could be discarded
  • when I worked with video clips in my Three.js project, checking for the xhr’s onload event was not enough to get the moment when everything was completed, I had to check for the onreadystatechange event, the readystate value and the status code as well; sure, I didn’t use any Three.js built in loaders or anything like that, but just in case

Hopefully one or some of these will help you figure out the issue and solve it.