Hi I’m new to ThreeJS and I’m working on displaying a model and playing its animation on loop. I was able to get it to work but I ran into a problem which I think is from the model itself.
The animation I want to play is “Action_Crawl”. It has 86 frames but the total duration is 22s!!? The real crawling action only takes about 2s and after that the model just freezes for the rest of the duration before doing another loop.
Set the action duration to 2s but it just speeds up everything
Opened the Action_Crawl.FBX in blender to confirm the animation only lasts 86 frames (I don’t know Blender I just installed it yesterday out of curiousity)
This model has a lot of animations and all of them have the same problem with excessive time. Is this something I can change in js or does it requires modification inside the model? It comes with glb, gltf, and all of the fbx files for every animation.
Hey thank you for your tip. I was able to create a subclip and turned it into an action. Now I’m trying to play this new action but it’s not working. I did some research and I think the animation mixer needs to be updated? I’ve been trying to update it but I don’t think I’m doing it right. What am I missing?
import React, { useEffect, useRef } from 'react'
import { useGLTF, useAnimations } from '@react-three/drei'
import { AnimationMixer, AnimationUtils } from 'three'
export default function Model(props) {
const group = useRef()
const { nodes, materials, animations } = useGLTF('/raccoon.gltf')
const { actions } = useAnimations(animations, group)
useEffect(() => {
// Create animmation mixer
const mixer = new AnimationMixer(group.current);
// Get the clip of the action
console.log(actions.Action_Crawl)
const crawlClip = actions.Action_Crawl.getClip();
// Create sub clip
const crawl_subClip = AnimationUtils.subclip(crawlClip, 'crawl_trim', 1, 20);
// Convert sub clip into Action
const crawl_subAction = mixer.clipAction(crawl_subClip);
// Play action
console.log(crawl_subAction)
crawl_subAction.play();
// HOW TO UPDATE ANIMATION MIXER?
const updateMixer = () => {
mixer.update(0.1); // You can adjust the delta time as needed
};
return () => {
mixer.stopAllAction();
};
})
return (
<group ref={group} {...props} dispose={null}>
<group name="Sketchfab_Scene">
<group name="Sketchfab_model" rotation={[-Math.PI / 2, 0, 0]}>
<group name="d694477a516e4500907a8e651d27b4d1fbx" rotation={[Math.PI / 2, 0, 0]}>
<group name="Object_2">
<group name="RootNode">
<group name="CG" position={[0, 33.046, 0]} rotation={[-1.605, -0.004, -1.449]}>
<group name="Object_5">
<primitive object={nodes._rootJoint} />
<group name="Object_63" rotation={[-Math.PI / 2, 0, 0]} />
<skinnedMesh name="Object_64" geometry={nodes.Object_64.geometry} material={materials.Material_28} skeleton={nodes.Object_64.skeleton} />
</group>
</group>
<group name="Raccoon_Poly_Art" rotation={[-Math.PI / 2, 0, 0]} />
</group>
</group>
</group>
</group>
</group>
</group>
)
}
useGLTF.preload('/raccoon.gltf')
I also printed the original action and the trimmed action to check. The trimmed action has LocalRoot = null, unlike the original one. Is this a problem?
I see two potential reasons. But this is just a guess, since your code is not written in vanilla three.js. I’m not familiar with react three code skip.
Try to create your subclip from an animation, not from a clip. Set a duration too: THREE.AnimationUtils.subclip( myAnimation, 'crawl_trim', 1, 20).setDuration(3).play();
then make sure your action is enabled crawl_subAction.enabled = true;