Animations in threejs, help needed to create a simpler abstraction

I am working on a small animation-helper for a tool that i make, gltfjsx. Currently it extracts animations by creating a new mixer, then it turns clips into actions. But it doesn’t really feel straight forward, i have a hard time wrapping my head around the animation api in general. So i tried to create a small hook for it:

const { clips, names, actions, mixer } = useAnimationMixer(clips, root)

This allows the user to simply start actions like so:

actions.idle.play()

Example (click on Suzy): https://codesandbox.io/s/react-three-fiber-gltf-camera-animation-forked-pecl6?file=/src/Model.js

My question

It still seems kind of hard, actions that are played don’t stop those that previously did play, it doesn’t fade, there would be lots of manual labour involved still to work with it. Are there things that you think can be abstracted (like you play action xyz, which fades from the previous one automatically), and what would your assumptions be if some abstraction attempts to take some control. Is is even worth it to spend time on this or will animation always be something you need to fiddle with a lot and that’s just the way it is?

TLDR, if you have ever made a game or used animation, did you want something that made the process easier, and in what way did you think that would be possible?

You may want to consider Blend Trees as an abstraction; they’re common in Unity and Unreal. There’s been some discussion of adding that on top of the lower-level animation system in three.js here: https://github.com/mrdoob/three.js/issues/6935.

But it might still be more complicated than you need; here’s a simpler abstraction I wrote a while back for A-Frame:

This example is also a useful one, as it features a mix of animations played in a loop with other animations layered on top, on demand:

2 Likes

this is perfect! the aframe extras seem really easy to use and that’s the direction i would like it to go. i made a first draft today and will try to add some options later.

1 Like
import { useAnimations, useFBX } from "@react-three/drei";
import { useEffect } from "react";

const model = () => {

  const fbx = useFBX("./test.fbx");
  const { animations } = useFBX("./test_anim.fbx");

  const { ref, actions, names } = useAnimations(animations)

  useEffect(() => {
    actions.test_anim.play()
  });

  return (
    <>
      <primitive
        ref={ref}
        object={fbx}
        position={[0, -20, 20]}
        scale={[1, 1, 1]}
      />
    </>
  );
};

export default model;

I am having this problem, I know that test_anim is giving a null value but I cannot make this animated fbx file run.

Solved it.

import { useAnimations, useFBX } from "@react-three/drei";
import { useEffect } from "react";

const model = () => {
  const fbx = useFBX("./test.fbx");
  const { animations } = useFBX("./test_anim.fbx");

  console.log(animations);
  const { actions, names  } = useAnimations(animations, fbx);
  
  useEffect(() => {
    actions[names[names.length-1]].play();
  });

  return (
    <>
      <group>
        <primitive
          object={fbx}
          position={[0, -150, 20]}
          scale={[2, 2, 2]}
        />
      </group>
    </>
  );
};

export default model;