Three.js 不在 React 中播放动画
Three.js doesn't play animation in React
我在 React 应用程序中加载了从 Sketchfab 下载的 GLTF 模型。模型加载完美,但动画根本无法播放。我尝试了不同的方法。有什么想法吗?
function Model({ url }) {
const model = useRef()
const { scene, animations } = useLoader(GLTFLoader, url)
const [mixer] = useState(() => new THREE.AnimationMixer())
useEffect(() => void mixer.clipAction(animations[0], group.current).play(), [])
return(
<primitive
ref={model}
object={scene}
/>
)
}
解决方案
- 我不得不使用节点而不是场景和 select "RootNode" (console.log 节点并选择在我看来是主节点,模型包含十几个节点)
- 使用 useFrame
按帧更新混音器
- 为模型应用动画(有点更新)
工作代码:
function Model({ url }) {
const group = useRef()
const { nodes, scene, materials, animations } = useLoader(GLTFLoader, url)
const actions = useRef()
const [mixer] = useState(() => new THREE.AnimationMixer())
useFrame((state, delta) => mixer.update(delta))
useEffect(() => {
actions.current = { idle: mixer.clipAction(animations[0], group.current) }
actions.current.idle.play()
return () => animations.forEach((clip) => mixer.uncacheClip(clip))
}, [])
return(
<group ref={group} dispose={null}>
<primitive
ref={group}
name="Object_0"
object={nodes["RootNode"]}
/>
</group>
)
}
现在可以了
您需要在组件内的 useFrame 中调用 mixer.update(delta):
import { useFrame } from 'react-three-fiber'
function Model({url}) {
.
.
.
useFrame((scene, delta) => {
mixer?.update(delta)
})
.
.
.
- 将您的 glb 文件放入 public 文件管理器。
import { Suspense, useEffect, useRef } from "react";
import { useAnimations, useGLTF } from "@react-three/drei";
export const Character = (props: any) => {
const ref = useRef() as any;
const glf = useGLTF("assets/Soldier.glb");
const { actions } = useAnimations(glf.animations, ref);
useEffect(() => {
actions.Run?.play();
});
return (
<Suspense fallback={null}>
<primitive
ref={ref}
object={glf.scene}
/>
</Suspense>
);
};
我在 React 应用程序中加载了从 Sketchfab 下载的 GLTF 模型。模型加载完美,但动画根本无法播放。我尝试了不同的方法。有什么想法吗?
function Model({ url }) {
const model = useRef()
const { scene, animations } = useLoader(GLTFLoader, url)
const [mixer] = useState(() => new THREE.AnimationMixer())
useEffect(() => void mixer.clipAction(animations[0], group.current).play(), [])
return(
<primitive
ref={model}
object={scene}
/>
)
}
解决方案
- 我不得不使用节点而不是场景和 select "RootNode" (console.log 节点并选择在我看来是主节点,模型包含十几个节点)
- 使用 useFrame 按帧更新混音器
- 为模型应用动画(有点更新)
工作代码:
function Model({ url }) {
const group = useRef()
const { nodes, scene, materials, animations } = useLoader(GLTFLoader, url)
const actions = useRef()
const [mixer] = useState(() => new THREE.AnimationMixer())
useFrame((state, delta) => mixer.update(delta))
useEffect(() => {
actions.current = { idle: mixer.clipAction(animations[0], group.current) }
actions.current.idle.play()
return () => animations.forEach((clip) => mixer.uncacheClip(clip))
}, [])
return(
<group ref={group} dispose={null}>
<primitive
ref={group}
name="Object_0"
object={nodes["RootNode"]}
/>
</group>
)
}
现在可以了
您需要在组件内的 useFrame 中调用 mixer.update(delta):
import { useFrame } from 'react-three-fiber'
function Model({url}) {
.
.
.
useFrame((scene, delta) => {
mixer?.update(delta)
})
.
.
.
- 将您的 glb 文件放入 public 文件管理器。
import { Suspense, useEffect, useRef } from "react";
import { useAnimations, useGLTF } from "@react-three/drei";
export const Character = (props: any) => {
const ref = useRef() as any;
const glf = useGLTF("assets/Soldier.glb");
const { actions } = useAnimations(glf.animations, ref);
useEffect(() => {
actions.Run?.play();
});
return (
<Suspense fallback={null}>
<primitive
ref={ref}
object={glf.scene}
/>
</Suspense>
);
};