Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Behavior of useAnimations has changed in 9.81.2: it returns to T-Pose for a moment when switching animations. #2340

Open
koike-vdsa opened this issue Feb 10, 2025 · 0 comments
Labels
question Further information is requested

Comments

@koike-vdsa
Copy link

koike-vdsa commented Feb 10, 2025

What is your question:

I am following this R3F tutorial on YouTube, where animation transitions should be smooth. However, in my environment, I noticed that a T-pose briefly appears when switching animations.

After investigating step by step, I found that this issue occurs after upgrading @react-three/drei from 9.81.1 to 9.81.2.

Steps to Reproduce

  1. Install @react-three/[email protected] → Animations transition smoothly.
  2. Upgrade to @react-three/[email protected] → A T-pose briefly appears when switching animations.
Open the toggle to see the problem in a Gif image

Image

Version Tests

Try Three.js @types-three R3F R3F drei Remarks
1 0.157.0 0.157.0 8.13.3 9.79.4 Tutorial Version (OK)
2 0.157.0 0.157.0 8.17.14 9.81.1 OK
3 0.173.0 0.173.0 8.17.14 9.81.2 NG (T-pose issue)
4 0.173.0 0.173.0 8.17.14 9.121.4 NG (All Latest)

Possible Cause

Looking at the release notes for 9.81.2, I found this commit:

🔗 Commit: "fix(useAnimations): correctly stop all actions when clips change"

This commit moves mixer.stopAllAction() from a cleanup function inside useEffect to execute immediately when clips change.

This seems to affect animation switching behavior.

Question

What is the recommended way to migrate to 9.81.2 without animations unexpectedly stopping or briefly showing a T-pose?

Here is my environment:

  • React 18 + TypeScript
  • Using a free avatar from Ready Player Me
  • Animations from Mixamo

Here is my code:

/*
Auto-generated by: https://github.com/pmndrs/gltfjsx
Command: npx [email protected] public/models/646d9dcdc8a5f5bddbfac913.glb -o src/components/Avatar.jsx -r public
*/

import { useAnimations, useFBX, useGLTF } from "@react-three/drei";
import React, { useEffect, useMemo, useRef, useState } from "react";

export function Avatar(props) {
  console.log("Rendering Avatar");

  // import model
  const { nodes, materials } = useGLTF("/models/Alfred.glb");
  // import animations
  const { animations: idleAnimation } = useFBX("/animations/Idle.fbx");
  const { animations: angryAnimation } = useFBX("/animations/Angry Gesture.fbx");
  const { animations: greetingAnimation } = useFBX("/animations/Standing Greeting.fbx");
  idleAnimation[0].name = "Idle";
  angryAnimation[0].name = "Angry";
  greetingAnimation[0].name = "Greeting";

  const [animation, setAnimation] = useState("Idle");
  const group = useRef();
  const { actions } = useAnimations([idleAnimation[0], angryAnimation[0], greetingAnimation[0]], group);

  const switchAnimation = React.useCallback(() => {
    const animations = ["Idle", "Angry", "Greeting"];
    const nextAnimation = animations[Math.floor(Math.random() * animations.length)];
    setAnimation(nextAnimation);
  }, [actions]);

  useEffect(() => {
    actions[animation].reset().fadeIn(0.5).play();
    return () => actions[animation].fadeOut(0.5);
  }, [animation]);

  useEffect(() => {
    const interval = setInterval(switchAnimation, 2000);
    return () => clearInterval(interval);
  }, [switchAnimation])

  return (
    <group {...props} dispose={null} ref={group}>
      <primitive object={nodes.Hips} />
      <skinnedMesh geometry={nodes.Wolf3D_Body.geometry} material={materials.Wolf3D_Body} skeleton={nodes.Wolf3D_Body.skeleton} />
      <skinnedMesh geometry={nodes.Wolf3D_Outfit_Bottom.geometry} material={materials.Wolf3D_Outfit_Bottom} skeleton={nodes.Wolf3D_Outfit_Bottom.skeleton} />
      <skinnedMesh geometry={nodes.Wolf3D_Outfit_Footwear.geometry} material={materials.Wolf3D_Outfit_Footwear} skeleton={nodes.Wolf3D_Outfit_Footwear.skeleton} />
      <skinnedMesh geometry={nodes.Wolf3D_Outfit_Top.geometry} material={materials.Wolf3D_Outfit_Top} skeleton={nodes.Wolf3D_Outfit_Top.skeleton} />
      <skinnedMesh geometry={nodes.Wolf3D_Hair.geometry} material={materials.Wolf3D_Hair} skeleton={nodes.Wolf3D_Hair.skeleton} />
      <skinnedMesh name="EyeLeft" geometry={nodes.EyeLeft.geometry} material={materials.Wolf3D_Eye} skeleton={nodes.EyeLeft.skeleton} morphTargetDictionary={nodes.EyeLeft.morphTargetDictionary} morphTargetInfluences={nodes.EyeLeft.morphTargetInfluences} />
      <skinnedMesh name="EyeRight" geometry={nodes.EyeRight.geometry} material={materials.Wolf3D_Eye} skeleton={nodes.EyeRight.skeleton} morphTargetDictionary={nodes.EyeRight.morphTargetDictionary} morphTargetInfluences={nodes.EyeRight.morphTargetInfluences} />
      <skinnedMesh name="Wolf3D_Head" geometry={nodes.Wolf3D_Head.geometry} material={materials.Wolf3D_Skin} skeleton={nodes.Wolf3D_Head.skeleton} morphTargetDictionary={nodes.Wolf3D_Head.morphTargetDictionary} morphTargetInfluences={nodes.Wolf3D_Head.morphTargetInfluences} />
      <skinnedMesh name="Wolf3D_Teeth" geometry={nodes.Wolf3D_Teeth.geometry} material={materials.Wolf3D_Teeth} skeleton={nodes.Wolf3D_Teeth.skeleton} morphTargetDictionary={nodes.Wolf3D_Teeth.morphTargetDictionary} morphTargetInfluences={nodes.Wolf3D_Teeth.morphTargetInfluences} />
      <skinnedMesh name="Wolf3D_Beard" geometry={nodes.Wolf3D_Beard.geometry} material={materials.Wolf3D_Beard} skeleton={nodes.Wolf3D_Beard.skeleton} morphTargetDictionary={nodes.Wolf3D_Beard.morphTargetDictionary} morphTargetInfluences={nodes.Wolf3D_Beard.morphTargetInfluences} />
    </group>
  );
}

useGLTF.preload("/models/Alfred.glb");

Thanks for your help!

@koike-vdsa koike-vdsa added the question Further information is requested label Feb 10, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

1 participant