Three.js为GLTF模型应用材质时出现未定义错误的排查求助
错误触发原因
- Three.js的
traverse方法会递归遍历目标对象下所有层级的全部节点,包含Group、Mesh、Camera、Light等所有类型的3D对象,并非只遍历第一层子节点。 - 你当前的代码未做任何判断,直接硬编码取当前节点的
children[0]、children[1]、children[2],当遍历到没有子元素的叶子节点(比如你场景里的Mesh本身)、或者子元素数量不足3个的节点时,访问对应索引的children就会得到undefined,对undefined设置material属性就会抛出该报错。 - 材质能正常生效是因为遍历到你目标的父级Group节点时,该节点确实有3个子元素,赋值操作执行成功了;报错是后续遍历到其他节点时触发的,不影响之前已经完成的赋值操作。
- 你测试时控制台日志看起来矛盾的原因是:正常输出的是遍历到父Group时的日志,报错是遍历到其他节点时的输出,两者属于不同次的遍历回调执行结果。
解决方案
方案1:按节点名称精准匹配(最稳妥,推荐)
导出GLB模型前,在建模工具(Blender、C4D等)中给三个需要替换材质的Mesh分别设置唯一名称,比如midMesh、topMesh、botMesh,遍历的时候直接过滤Mesh节点并匹配名称赋值:
gltfObject.traverse((child) => { // 先过滤掉非Mesh类型的节点,避免不必要的判断 if (!child.isMesh) return if (child.name === 'midMesh') child.material = MidMaterial if (child.name === 'topMesh') child.material = TopMaterial if (child.name === 'botMesh') child.material = BotMaterial })
该方案不受模型层级结构变动影响,只要Mesh名称不变就可以正常运行。
方案2:判断子节点数量后再赋值
如果不方便修改模型命名,可以先判断当前节点的子元素数量是否满足要求,再执行赋值操作:
gltfObject.traverse((ChildGLTF) => { // 只处理子元素数量≥3的节点 if (ChildGLTF.children.length < 3) return ChildGLTF.children[0].material = MidMaterial; ChildGLTF.children[1].material = TopMaterial; ChildGLTF.children[2].material = BotMaterial; })
如果你的场景里只有一个节点满足子元素数量≥3的条件,该方案可以直接解决问题。
方案3:限定只处理目标父节点
如果你的目标父节点有固定名称,可以直接匹配父节点名称后再处理子元素:
gltfObject.traverse((ChildGLTF) => { if (ChildGLTF.name !== '你的父节点名称') return ChildGLTF.children[0].material = MidMaterial; ChildGLTF.children[1].material = TopMaterial; ChildGLTF.children[2].material = BotMaterial; })
内容的提问来源于stack exchange,提问作者oh pew pew
相关产品推荐
相关产品推荐

