Cant play animation from GLTFjsx GLTF file

Hi all,

I’m trying to play an animation I have set up in a GLTF model but still cant get it to work.

Ive been trying for a while and read many forum posts on the best way to approack this. I have decided after reading How to use the animation that comes with the .gltf file that i downloaded in sketchfab - #2 by drcmda that maybe r3f is the way to go to simplify the process.

I have successfully managed to covert the GLTF using the online GLTF/jsx converter and created a r3f project that loads the file but have tried many different variations of the useEffect hook to no effect.

Here is the app.js:
import “./App.css”;
import { Canvas } from “@react-three/fiber”;
import { Environment, OrbitControls } from “@react-three/drei”;
import { Suspense } from “react”;
import Model from “./Model”;

function App() {
return (










);
}

export default App;

and the top few lines of Model.js:
*
Auto-generated by: GitHub - pmndrs/gltfjsx: 🎮 Turns GLTFs into JSX components
*/

import React, { useRef } from “react”;
import { useGLTF, PerspectiveCamera, useAnimations } from “@react-three/drei”;

export default function Model(props) {
const group = useRef();
const { nodes, materials, animations } = useGLTF(“/model.gltf”);
const { actions } = useAnimations(animations, group);

return (
<group ref={group} {…props} dispose={null}>

When I run the code I get the following warning:

Line 11:11: ‘actions’ is assigned a value but never used no-unused-vars

I have tried this line in the Model.js:

useEffect(() => {
actions[‘CameraAction.003’].play(), )

but it keeps throwing up another error message about useEffect needing dependancies. Where does the ‘CameraAction.003’ string come from? Does the GLTF file in the public folder need to be a GLB?

Any help would be much appreciated and if Im better off going back to straight old Three.js please let me know?

Thanks

1 Like

It sets everything up but playing then is up to you. If you console.log actions in the useEffect you will see the names, they come from the model. CameraAction3 is an action that must have come from some model.

Btw these helpers are there to make things a little easier but you can use just the regular mixer as you always would. You will also have to know the action name though.

Hi @drcmda , thanks for getting back to me.

After running, useEffect (() => { console.log(actions)}) the console returns:
image

Does this mean the action is called Action?

I have tried running actions like this:
useEffect(() => (actions[“Action”].play()), )

But get the following error message in the terminal:
Line 17:47: React Hook useEffect has a missing dependency: ‘actions’. Either include it or remove the dependency array react-hooks/exhaustive-deps

And this in the console:

Thanks again for any help!

Does this mean the action is called Action?

it does. your model contains one action called “Action”. the names can be set in blender and are arbitrary.

But get the following error message

play() returns an action, but useEffects return is reserved. so either

useEffect(() => void actions.Action.play(), [actions])

or

useEffect(() => {
  actions.Action.play()
}, [actions])

the return of useEffect is the clean-up callback.

useEffect(() => {
  const interval = setInterval(() => console.log("👋"), 1000)
  return () => clearInterval(interval)
}, [])

here’s an example. click stacy to cycle through her actions

Hi @drcmda

Thanks again for the guidance,

Using your second option above like this:

import React, { useEffect, useRef } from “react”;
import { useGLTF, PerspectiveCamera, useAnimations } from “@react-three/drei”;

export default function Model(props) {
const group = useRef();
const { nodes, materials, animations } = useGLTF(“/model.gltf”);
const { actions } = useAnimations(animations, group);

useEffect(() => {
actions.Action.play()
}, [actions])

return (
<group ref={group} {…props} dispose={null}>

I am receiving no errors in the console but have the following warning in the terminal:

WARNING in ./node_modules/@mediapipe/tasks-vision/vision_bundle.mjs
Module Warning (from ./node_modules/source-map-loader/dist/cjs.js):
Failed to parse source map from ‘D:\bt-cloud\One_Drive-extracted\05_Learning\code\web-building\MakerVerde_\Part2Project\ReactThreeFibre\my-app\node_modules@mediapipe\tasks-vision\vision_bundle_mjs.js.map’ file: Error: ENOENT: no such file or directory, open ‘D:\bt-cloud\One_Drive-extracted\05_Learning\code\web-building\MakerVerde_\Part2Project\ReactThreeFibre\my-app\node_modules@mediapipe\tasks-vision\vision_bundle_mjs.js.map’

webpack compiled with 1 warning

I’ve searched the node_modules directory and the files the warning references are in there.

Is it possible there is an issue with my folder structure?

The browser is showing the model but no animation with what seems to be a default perspective camera and position. Do I need to deactivate the defaults?

Kind regards,

mv

You are probably using react-scripts with webpack5

One option you have : Drei 9.74.0 introduces new console warning related to @mediapipe\tasks-vision · Issue #1572 · pmndrs/drei · GitHub

Thanks @seanwasere,

The.env file has eliminated the error messages but the model still fails to animate.

I’m thinking it’s something to do with the camera setup?

In your original post in this thread, your function App is empty

I can’t tell from reading this thread whether you got past this problem or not.

Anyway, here is another minimal example for reference.
Example : Load animation from separate file

test

1 Like

Hi @seanwasere,

Here is the top of the model.js file, its pretty long and the rest is just lights and meshes:

/*
Auto-generated by: GitHub - pmndrs/gltfjsx: 🎮 Turns GLTFs into JSX components
*/

import React, { useEffect, useRef } from “react”;
import { useGLTF, PerspectiveCamera, useAnimations } from “@react-three/drei”;

export default function Model(props) {
const group = useRef();
const { nodes, materials, animations } = useGLTF(“/model.gltf”);
const { actions } = useAnimations(animations, group);

useEffect(() => void actions.Action.play(), [actions])

return (
<group ref={group} {…props} dispose={null}>

<PerspectiveCamera
name=“Camera”
makeDefault={false}
far={1000}
near={0.1}
fov={32.269}
position={[-12.904, 4.262, 19.726]}
rotation={[-0.123, -0.53, -0.075]}
/>

And here is the App.js:

import "./App.css";
import { Canvas } from "@react-three/fiber";
import { Environment, OrbitControls } from "@react-three/drei";
import { Suspense } from "react";
import Model from "./Model";

export default function App() {
  return (
    <div className="App">
      <Canvas>
        <Suspense fallback={null}>
          <Model />
          <OrbitControls />
          <Environment preset="forest" background />
        </Suspense>
      </Canvas>
    </div>

);
}

I cant load my gltf because its over 8gb, its actually 36mb as a glb and 46mb as a gltf. If its needed for to enable you to comment I can use WeTransfer?

Any help would be greatly appreciated, I’m almost ready to go back to straight threejs now and figure it out there…

Just before I was going to send I did one more tweek and have discovered the issue was that perspective camera default was set to false, Ive flicked it true and its working now :slight_smile:

return (
<group ref={group} {…props} dispose={null}>

<PerspectiveCamera
name=“Camera”
makeDefault={true}
far={1000}
near={0.1}
fov={32.269}
position={[-12.904, 4.262, 19.726]}
rotation={[-0.123, -0.53, -0.075]}
/>

I do have another query about using a raytrace onclick method to access url’s I have set, as seen below in the mesh tags…
Basically there are art works displayed in my virtual gallery that I want to make clickable and link to external webpages:

        <mesh
          name="Part2Project15_ImagesForGalleryindexNoborigama-Raku"
          castShadow
          receiveShadow
          geometry={
            nodes["Part2Project15_ImagesForGalleryindexNoborigama-Raku"]
              .geometry
          }
          material={materials["Material.002"]}
        />
        <mesh
          name="Object772"
          castShadow
          receiveShadow
          geometry={nodes.Object772.geometry}
          material={materials["material-Plywood"]}
        />

Should I start a new post for this one?

8gb gltf is too large for my browser.
Maybe break you model into smaller parts and load on demand, or try ways to optimise it before compressing so that the browser can cope with the uncompressed result much better.

Ideally start a new post for new questions.

Anyway, maybe give wouter a try for loading urls from clicking something.

pmnd.rs example : Router Transitions. (loading from clicking a link)

my example : Loading from clicking a model. Uses the mesh onPointerDown event to change the route