Three.js Raycasting对导入OBJ模型无效 原生创建对象检测正常
问题核心原因
通过OBJLoader/MTLLoader加载的外部模型,返回值不是直接可被射线检测命中的Mesh对象,而是THREE.Group类型的嵌套容器,容器本身不携带几何体信息。射线检测实际命中的是Group内部嵌套的子网格对象,你直接拿命中对象的ID和外层Group的ID做相等判断,永远无法匹配成功。
这也是为什么直接用Three.js API创建的Box网格可以正常检测:Box是直接加入场景的独立Mesh,ID可以直接和命中结果匹配。
代码存在的具体问题
- 判断逻辑错误:遍历命中结果时始终只取
intersects[0]做比对,完全没有处理命中对象是模型子节点的场景 - 性能浪费:每帧递归检测场景下所有子对象,同时输出大量无意义控制台日志,运行时会造成不必要的性能开销
修复方案
- 先写一个工具函数,判断命中的网格是否属于目标模型组:
// 校验节点是否为目标模型的子元素 function checkIsChild(node, targetGroup) { let current = node; while (current) { if (current.id === targetGroup.id) return true; current = current.parent; } return false; }
- 替换原animate函数中的射线检测逻辑,不要全场景扫描,只把需要检测的对象加入检测列表,同时修正命中判断逻辑:
function animate(){ raycaster.setFromCamera(mousePosition, camera); // 组装需要检测的对象列表,避免全场景扫描 const detectList = [box, plane]; if (building) detectList.push(building); const intersects = raycaster.intersectObjects(detectList, true); let isHitBuilding = false; if (intersects.length > 0) { for (const item of intersects) { if (building && checkIsChild(item.object, building)) { isHitBuilding = true; break; } } } if (isHitBuilding) { console.log("鼠标触碰导入的建筑模型"); // 此处编写模型触碰后的交互逻辑,比如高亮、弹窗等 } renderer.render(scene, camera); }
额外排查点
如果改完还是无法检测,优先检查两个点:
- 导入的模型是否存在坐标偏移、缩放异常,导致模型实际位置和你视觉上看到的位置不重合
- 模型材质是否设置了
transparent: true且透明度为0,这类透明材质默认会被射线检测忽略(可以手动改材质的side属性为THREE.DoubleSide测试)
内容的提问来源于stack exchange,提问作者Noone
相关产品推荐
相关产品推荐

