GLB created in blender using 'clamp to' to animate object along a curved path

I created an animated bird along a curved path in blender using the tool ‘clamp to’ a Bézier curve. In, the GLB model animation behaves exactly in blender, but in my project it just does not follow the curved path and has weird behaviors. In the gilt-viewer, the bird can flap its wings while following the path, but in my project it wanders around and the wings are not flapped. Not sure which part still needs to be implemented?
GLB file:
testanimations.glb (7.6 MB)

code of my project:

	// resource URL
	// called when the resource is loaded
	function ( gltf ) {
        const birdScene = gltf.scene;
                    node.material = new THREE.MeshBasicMaterial({ color: 0xE9D9FA });

		scene.add( birdScene );

        bird = gltf;

// // Create an AnimationMixer, and get the list of AnimationClip instances
const birdMixer = new THREE.AnimationMixer( birdScene );
const clips = bird.animations;

// // Play action1
const clipAction1 = THREE.AnimationClip.findByName( clips, 'Action1' );
const action1 = birdMixer.clipAction( clipAction1 );;


	// called while loading is progressing
	function ( xhr ) {

		console.log( ( xhr.loaded / * 100 ) + '% loaded' );

	// called when loading has errors
	function ( error ) {

		console.log( 'An error happened' );


It also works ok in my viewer
How are you updating the mixer in your animation loop?

function animate() {
	requestAnimationFrame( animate );

    const delta = clock.getDelta();

    if (mixer.length > 0){




	renderer.render( scene, camera );



I can’t see any problem from reading it since you are pasting parts of your code. The problem may be somewhere else.
I can’t copy and paste this and reproduce your problem.
And as I say, it worked on my viewer, and it works on Don Mccurdys viewer, so there is something strange in your code.
Are you sure that mixer.length > 0 ?
Is your mixer meant to be an array of mixers?
Do you see errors in the console?
The code you posted doesn’t show how you declared your variables, what scope they are declared, or if they are being modified somewhere else, so it’s all guesses.

If you do intend to have multiple animated models loaded with multiple mixers being updated, then this code below is almost the minimum you need. It loads 2 models, and starts two independent mixers playing.

Adjust imports for your environment.

import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'

const scene = new THREE.Scene()
scene.add(new THREE.AxesHelper(5))
scene.add(new THREE.AmbientLight())

const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 20)
camera.position.set(3, 3, 3)

const renderer = new THREE.WebGLRenderer()
renderer.setSize(window.innerWidth, window.innerHeight)

function onWindowResize() {
    camera.aspect = window.innerWidth / window.innerHeight
    renderer.setSize(window.innerWidth, window.innerHeight)
window.addEventListener('resize', onWindowResize, false)

new OrbitControls(camera, renderer.domElement)

const loader = new GLTFLoader()
const mixers = []

loader.load('testanimations.glb', function (gltf) {

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

    mixer.clipAction(THREE.AnimationClip.findByName(gltf.animations, 'Action1')).play()


loader.load('otherAnimatedModel.glb', function (gltf) {

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

    mixer.clipAction(THREE.AnimationClip.findByName(gltf.animations, 'NameOfClipAction')).play()


const clock = new THREE.Clock()
let delta = 0

function animate() {

    delta = clock.getDelta()

    mixers.forEach((m) => m.update(delta))

    renderer.render(scene, camera)


Thanks for suggestions! In the end I created and export 2 or 3 animals at a time in Blender and they were loaded and played correctly in Three.js environment. I actually had over 100 animals with animations, with 21 creations but multiplied in the environment.