How to use the animation that comes with the .gltf file that i downloaded in sketchfab

I have been struggling immensely to find solutions on how to play the animation that accompanies the .gltf model I downloaded from Sketchfab. Despite my efforts, I have been unable to resolve this issue. I am particularly seeking assistance on how to make the embedded animation work. It would be greatly appreciated if anyone could provide guidance or support. I am developing this project using React. Thank you in advance for your help.

import React, { Suspense, useEffect, useState } from "react";
import { Canvas } from '@react-three/fiber';
import { OrbitControls, Preload, useGLTF } from '@react-three/drei';

import CanvasLoader from '../Loader';

const Computers = () => {
  const computer = useGLTF('./robot_playground/scene.gltf')

  return (
    <mesh>
      <hemisphereLight intensity={0.15} groundColor="black" />
      <pointLight intensity={1} />
      <primitive 
        object={computer.scene}
        scale={1.13}
        position={[1.5,-1.5,0.08]}
        rotation={[-0.3,-0.5,0]}
      />
    </mesh>
  );
};

const ComputersCanvas = () => {
  return (
    <Canvas
      frameloop='demand'
      shadows
      camera={{ position: [0,1.5,3], fov: 65 }}
      gl={{ preserveDrawingBuffer: true }}
    >
      <Suspense>
        <Computers />
      </Suspense>

      <Preload all />
    </Canvas>
  );
};

export default ComputersCanvas

I tried various methods that I can find in this platform, and I also tried ChatGPT but still no success.

edit: I have checked that the GLTF file path is correct and confirmed that the file contains animations. Despite these efforts, the 3D model remains stationary. I would greatly appreciate any insights or suggestions on how to troubleshoot and resolve this issue. Thank you for your assistance!

import React, { Suspense, useEffect, useState } from "react";
import { Canvas, useFrame } from '@react-three/fiber';
import { OrbitControls, Preload, useGLTF } from '@react-three/drei';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
import { AnimationMixer } from 'three';

import CanvasLoader from '../Loader';

let mixer = null; // Declare mixer variable outside the component's scope

const Computers = () => {
  const gltf = useGLTF('./robot_playground/scene.gltf');

  useEffect(() => {
    const model = gltf.scene;
    const animations = gltf.animations;

    if (model && animations && mixer === null) {
      mixer = new AnimationMixer(model);

      const action = mixer.clipAction(animations[0]);
      action.play();
    }
  }, [gltf]);

  useFrame((_, delta) => {
    if (mixer) {
      mixer.update(delta);
    }
  });

  return (
    <mesh>
      <hemisphereLight intensity={0.15} groundColor="black" />
      <pointLight intensity={1} />
      <primitive 
        object={gltf.scene}
        scale={1.13}
        position={[1.5,-1.5,0.08]}
        rotation={[-0.3,-0.5,0]}
      />
    </mesh>
  );
};

const ComputersCanvas = () => {
  useEffect(() => {
    const loader = new GLTFLoader();
    loader.load('./robot_playground/scene.gltf', (gltf) => {
      const model = gltf.scene;
      const animations = gltf.animations;

      if (model && animations && mixer === null) {
        mixer = new AnimationMixer(model);

        const action = mixer.clipAction(animations[0]);
        action.play();
      }
    });
  }, []);

  return (
    <Canvas
      frameloop='demand'
      shadows
      camera={{ position: [0,1.5,3], fov: 65 }}
      gl={{ preserveDrawingBuffer: true }}
    >
      <Suspense>
        <Computers />
      </Suspense>

      <Preload all />
    </Canvas>
  );
};

export default ComputersCanvas;

1 Like
npx gltfjsx scene.gltf --transform

it creates a ready made component and a small animation set up using drei/useAnimations. it looks like this: GLTF Animations - CodeSandbox useAnimation is a small helper around three.mixer, removing all the boilerplate and creating clips automatically.

see GitHub - pmndrs/gltfjsx: 🎮 Turns GLTFs into JSX components

ps. if gltfjsx doesn’t create actions for you, then the gltf has none, which might be the reason why your code above didn’t work.

1 Like

Thank you for this wonderful idea. I really appreciate your suggestion. I took the time to restructure my code based on your input. However, I’m still experiencing an issue with my 3D model. It’s not moving as expected. I’ve double-checked my code, but I can’t seem to find the cause of the problem. I would greatly appreciate any further assistance or guidance you can provide to help me resolve this issue.

Here is my code:

import React, { Suspense } from "react";
import { Canvas, useFrame } from '@react-three/fiber';
import Model from "./Scene";
import { Preload } from '@react-three/drei';

import CanvasLoader from '../Loader';

const ComputersCanvas = () => {
  return (
    <Canvas
      frameloop='demand'
      shadows
      camera={{ position: [0,1.5,3], fov: 65 }}
      gl={{ preserveDrawingBuffer: true }}
    >
      <Suspense>
        <Model 
          scale={1.13}
          position={[1.5,-1.5,0.08]}
          rotation={[-0.3,-0.5,0]}
        />
      </Suspense>
      <mesh>
        <hemisphereLight intensity={0.15} groundColor="black" />
        <pointLight intensity={1} />
      </mesh>
      <Preload all />
    </Canvas>
  );
};

export default ComputersCanvas;

and here is the jsx of my model:
Scene.jsx (23.3 KB)

i think you need to re-check in blender rather. all you’re doing at this point is play the keyframe animation.

1 Like

I tried using this code:

import React, { useEffect, useRef } from 'react';
import { useGLTF, useAnimations } from '@react-three/drei';
import * as THREE from 'three';

export default function Model(props) {
  const group = useRef();
  const { nodes, materials, animations } = useGLTF('/robot_playground/scene-transformed.glb');
  const { actions, mixer, ref } = useAnimations(animations, group);

  useEffect(() => {
    // Play the animation
    actions.animation_0.play();
  }, [actions]);

  // Animation loop
  useEffect(() => {
    const clock = new THREE.Clock();

    const animate = () => {
      const delta = clock.getDelta();
      mixer.update(delta);

      // Request the next animation frame
      requestAnimationFrame(animate);
    };

    // Start the animation loop
    animate();
  }, [mixer]);

  return (
    <group ref={ref} {...props}>
      {/* Your existing code */}
    </group>
  );
}


It only moves when I scroll or resize my browser or just interacting with the browser.

this is your problem. demand means it doesn’t render, it just stops, unless you change a prop somewhere in the scene, or you call invalidate(). remove the frameloop props from canvas, employ it only when you know what you’re doing and how to use it.

ps, you don’t need to register requestAnimationFrames, useFrame is already doing that, and more then 1 raf will hurt performance badly. it’s just this

useFrame((state, delta) => {
  mixer.update(delta)
})

but not even that is needed because useAnimations does this for you automatically. you don’t need to do anything, just play the animation.

pps. you could integrate animations with frameloop=demand, but you would have to invalidate while and when it’s playing.

2 Likes

Please accept my apologies. As a beginner in three.js, I’ve been relying on a tutorial to guide me through the process. However, I’ve been struggling with getting the animation to work properly, and it was only after removing the frameloop that it finally started playing correctly. I’m truly grateful for your assistance in helping me resolve this issue. Thank you so much.

This is my final code:

import React, { useEffect, useRef } from 'react'
import { useGLTF, useAnimations } from '@react-three/drei'

export default function Model(props) {
  const group = useRef()
  const { nodes, materials, animations } = useGLTF('/robot_playground/scene-transformed.glb')
  const { actions } = useAnimations(animations, group)

  console.log(animations);
  useEffect(() => {
    actions.Experiment.play();
  }, [actions]);