Three.js导入带开合动画的雨伞模型后动画异常求助
雨伞3D模型动画在React Three Fiber中异常的解决指南
问题背景
- 购入的雨伞3D模型自带开合动画,在Blender中预览完全正常
- 导入React Three Fiber项目后,模型显示两个动画均不符合预期:一个仅实现雨伞旋转,另一个仅让推杆上下移动,无法联动伞面及支撑杆
- 已确认项目代码无问题,推测问题出在Blender的模型绑定或导出设置,但缺乏Blender使用经验
用户提供的项目代码:
import * as React from 'react'; import { Canvas, useFrame } from '@react-three/fiber'; import { Suspense, useState, useRef, useEffect } from 'react'; import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'; import { OrbitControls, useGLTF } from '@react-three/drei'; import * as THREE from 'three'; const Model = ({ playAnimation }) => { const gltf = useGLTF(require("../svg/Part3.glb")); const mixer = useRef(); // Increase the scale to make the model larger gltf.scene.scale.set(200, 200, 200); // Set up animation mixer if (!mixer.current) { mixer.current = new THREE.AnimationMixer(gltf.scene); gltf.animations.forEach((animation) => { const action = mixer.current.clipAction(animation); action.play(); }); console.log(gltf.animations) } // Update the animation mixer on each frame useFrame((state, delta) => mixer.current.update(delta)); // Play animation when playAnimation is true useEffect(() => { if (playAnimation) { mixer.current.timeScale = 1; } else { mixer.current.timeScale = 0; } }, [playAnimation]); return <primitive object={gltf.scene} />; }; const Umbrella = () => { const [playAnimation, setPlayAnimation] = useState(false); const handleButtonClick = () => { setPlayAnimation(!playAnimation); }; return ( <div> <Canvas camera={{ position: [0, 0, 1000], fov: 75, near: 1, far: 5000 }} style={{ backgroundColor: "black", position: "relative", width: "100%", height: "90vh" }}> <directionalLight position={[2000, 2000, 2000]} intensity={1} color="white" /> <pointLight position={[10, 10, 10]} intensity={0.6} /> <Suspense fallback={null}> <Model playAnimation={playAnimation} /> </Suspense> <OrbitControls /> </Canvas> <button onClick={handleButtonClick}>{playAnimation ? 'Pause Animation' : 'Play Animation'} </button> </div> ); }; export default Umbrella;
解决步骤
1. 验证Blender中的骨骼绑定有效性
打开模型文件,按以下步骤操作:
- 切换到姿态模式(快捷键
Ctrl+Tab选择姿态模式) - 选中推杆对应的骨骼,拖动它,观察伞面和支撑杆是否跟随运动
- 如果跟随正常:说明绑定没问题,问题出在动画导出环节
- 如果不跟随:需要重新绑定骨骼
- 切换回物体模式,先选中伞面/支撑杆模型,再选中骨骼对象
- 按
Ctrl+P,选择自动权重完成模型与骨骼的绑定
2. 烘焙动画到骨骼(解决GLTF导出兼容性)
Blender中部分非骨骼驱动的动画导出后无法被Three.js正确识别,需要将动画烘焙到骨骼:
- 选中骨骼对象,切换到图形编辑器,顶部菜单选择动作编辑器
- 在动作编辑器中选中目标开合动画,点击顶部菜单编辑 > 烘焙动作
- 在弹出的烘焙设置中,勾选仅骨骼、清除关键帧,点击确定完成烘焙
3. 按标准设置导出GLB格式
导出时确保以下设置正确,避免兼容性问题:
- 选中模型和骨骼对象,点击文件 > 导出 > glTF 2.0
- 在导出面板中:
- 勾选动画选项,确保动画数据被导出
- 确认骨骼选项已勾选
- 格式选择GLB(二进制格式,Three.js支持更稳定)
- 取消勾选不必要的选项(如相机、灯光,除非项目需要)
4. 项目中动画的额外验证(可选)
虽然你确认代码无问题,但可以做以下检查:
- 控制台打印
gltf.animations,查看动画的名称和轨道目标是否为骨骼(而非物体本身) - 尝试单独播放目标开合动画,避免同时播放多个冲突动画:
// 替换原有的动画遍历代码 if (!mixer.current) { mixer.current = new THREE.AnimationMixer(gltf.scene); // 筛选出开合相关的动画(根据实际动画名称调整判断条件) const targetAnim = gltf.animations.find(anim => anim.name.includes("open") || anim.name.includes("close")); if (targetAnim) { const action = mixer.current.clipAction(targetAnim); action.play(); } console.log(gltf.animations); }
内容的提问来源于stack exchange,提问作者Benjamin Galler
相关产品推荐
相关产品推荐

