如何将带Shape Keys的Blender GLB模型导入ThreeJS/react-three-fiber?
带有多个Shape Keys的Blender GLB模型导入react-three-fiber时触发TypeError错误
错误信息
TypeError: Cannot read properties of undefined (reading 'length')
问题说明
当Blender模型仅含'Basis'形状键或无形状键时,能正常在react-three-fiber(r3f)中加载;但添加第二个形状键后导出GLB再导入就会触发上述错误。需要解决Blender导出前的正确设置,或r3f侧的处理方法,也接受实现Mesh形状动画的替代方案。
复现步骤
- 在Blender中新建带立方体网格的文件
- 给立方体添加两个形状键
- 将模型导出为GLB格式
- 执行
npx gltfjsx cube.glb生成React组件 - 引入组件后触发报错
自动生成的组件代码
import React, { useRef } from "react"; import { useGLTF } from "@react-three/drei"; export const Cube = (props) => { const { nodes, materials } = useGLTF("/cube.glb"); return ( <group {...props} dispose={null}> <mesh geometry={nodes.Cube.geometry} material={nodes.Cube.material} /> </group> ); }; useGLTF.preload("/cube.glb");
解决方案
Blender导出设置修正
- 导出GLB时,务必勾选Mesh分类下的"Shape Keys"选项,确保形状键数据被正确导出
- 导出前对立方体应用所有变换:选中立方体后按
Ctrl+A,依次应用位置、旋转、缩放,避免几何数据存在异常变换 - 检查形状键类型:新增的形状键需保持默认的"Relative"类型,不要修改为其他可能不兼容的类型
react-three-fiber侧处理
自动生成的组件未处理多形状键的morph数据,可手动修改组件来修复:
import React, { useRef, useEffect } from "react"; import { useGLTF } from "@react-three/drei"; export const Cube = (props) => { const meshRef = useRef(null); const { nodes } = useGLTF("/cube.glb"); useEffect(() => { const geometry = meshRef.current?.geometry; if (!geometry) return; // 确保morphTargets数组存在,避免读取length时出错 if (!geometry.morphTargets) { geometry.morphTargets = []; // 从morphAttributes转换为morphTargets(适配Three.js的期望格式) if (geometry.morphAttributes.position) { geometry.morphAttributes.position.forEach((attr, idx) => { geometry.morphTargets.push({ name: `shapeKey${idx}`, vertices: attr.array }); }); } // 更新几何体以生效 geometry.needsUpdate = true; } }, []); return ( <group {...props} dispose={null}> <mesh ref={meshRef} geometry={nodes.Cube.geometry} material={nodes.Cube.material} /> </group> ); }; useGLTF.preload("/cube.glb");
替代方案(形状动画实现)
如果上述方案仍有问题,可直接在r3f中实现形状动画:
- 使用
drei的MorphControls组件,直接绑定形状键的权重值来控制动画 - 简单动画可通过
useFrame钩子手动修改顶点数据,或使用Three.js的MorphTargetAnimation来管理
内容的提问来源于stack exchange,提问作者Jake Pitman
相关产品推荐
相关产品推荐

