Switching between animations from different fbx files applied on glb

I have here a model.glb, and two different fbx animations without skin. I want to switch between the animations smoothly; here is a working prototype with abrupt animation switching:

function Model(props) {
  const { nodes, scene } = useGLTF(props.url);
  const wavingAction = useFBX("Waving.fbx");
  const wavingAnimation = wavingAction.animations;
  const talkingAction = useFBX("Talking.fbx");
  const talkingAnimation = talkingAction.animations;

  const mixer = useRef(new AnimationMixer());

  useFrame((state, delta) => mixer.current.update(delta));

  useEffect(() => {
    mixer.current.clipAction(talkingAnimation[0], scene).play();
  }, [])

  useEffect(() => {
    const unsubscribe = subscribe(proxy, () => {
      if (proxy.isTalking) {
        mixer.current.clipAction(talkingAnimation[0], scene).play();
        mixer.current.clipAction(wavingAnimation[0], scene).stop();
      } else {
        mixer.current.clipAction(wavingAnimation[0], scene).play();
        mixer.current.clipAction(talkingAnimation[0], scene).stop();
      }
    });
    return () => {
      unsubscribe();
    };
  }, [proxy]); // Make sure to pass the correct dependencies

  return <primitive {...props} object={scene} />;
}

So I replaced the state conditions like this:

      if (proxy.isTalking) {
        mixer.current.clipAction(talkingAnimation[0], scene).fadeIn(0.5).play();
        mixer.current.clipAction(wavingAnimation[0], scene).fadeOut(0.5).stop();
      } else {
        mixer.current.clipAction(wavingAnimation[0], scene).fadeIn(0.5).play();
        mixer.current.clipAction(talkingAnimation[0], scene).fadeOut(0.5).stop();
      }

But now it is animating once and then bouncing back to the reset (T-pose) form.

there is also the possiblity of crossFadeTo(action); but I think I need to rearange my code structure and use the mixer differently.

three fiber, drei is welcome; but I also appriciate basic three.js.

Whether I’m using r3f or vanilla, the general sequence I use is,

  • fadeOut the old action,
  • reset, fadeIn and play the new action.

E.g., going from idle to walking

actions['idle'].fadeOut(0.1)
actions['walk'].reset().fadeIn(0.1).play()

R3F example : Obstacle Course
Vanilla/TypeScript : Kick Boxing

In react you could also use this basic pattern (untested, use it as a guide)

  const [action, setAction] = useState()

  useEffect(() => {
    action && action.reset().fadeIn(0.1).play()
    return () => {
      action && action.fadeOut(0.1)
    }
  }, [action])

then some where else in your code call
setAction(some-preloaded-animationAction)

Also. if you open your FBX animations in blender, you can then export them as glB and the file sizes will be much smaller.

1 Like

Don’t you need an animationmixer to handle the transition between the animations? I updated the component similar to your code; what I noticed is it is always going to the T-pose first and then from there transition to the next animation - shouldn’t it just fade into the next animation where ever the bones are at the moment when I say fadeout? - or does fadeout means: go to reset pose?

      if (proxy.isTalking) {
          // wavingClipAction.crossFadeTo(talkingClipAction, 1, true); not worked
          wavingClipAction.fadeOut(0.4)
          talkingClipAction.reset().fadeIn(0.1).play()
      } else {
        // talkingClipAction.crossFadeTo(wavingClipAction, 1, true); not worked
        talkingClipAction.fadeOut(0.4)
        wavingClipAction.reset().fadeIn(0.1).play()
      }

This here gives a better “transition” - at least it does not try to go to the T-pose:

      if (proxy.isTalking) {
          wavingClipAction.fadeOut(1)
          talkingClipAction.fadeIn(1).play()
          talkingClipAction.reset();
      } else {
        talkingClipAction.fadeOut(1)
        wavingClipAction.fadeIn(1).play()
        wavingClipAction.reset();
      }

what does reset() mean here? go back to the pose without animation applied? (T-pose in my case)

Hey, I have since tested what I suggested at the beginning, and it works.

Animation Controller : https://sbcode.net/react-three-fiber/animation-controller/
image

haha the fancy pose got me.
thx for the example! <3