Three.js网格上移时Raycaster检测沿Y轴镜像翻转如何解决
Three.js Raycaster检测结果沿Y轴翻转修复
问题现象
- 射线对场景内所有物体的检测结果沿Y轴方向翻转,立方体沿Y轴向上移动后,射线命中区域反而向下偏移
- 立方体处于默认原点位置时检测逻辑无明显异常
- 原生Three.js API创建的立方体、Blender导出的GLTF模型均复现该问题,排除模型资源本身异常

问题根因
鼠标坐标转NDC(标准化设备坐标)时Y轴计算逻辑错误:
- 浏览器事件返回的
clientY坐标系以页面顶部为原点,向下为正方向,顶部值为0,底部值为窗口高度 - Three.js射线使用的NDC坐标系以屏幕中心为原点,向上为Y轴正方向,屏幕顶部对应值为
1,底部对应值为-1
原代码未对Y轴做反向转换,直接套用X轴的计算逻辑,导致射线方向Y轴完全翻转。物体在Y=0原点位置时,正负0计算结果一致无异常,一旦物体沿Y轴偏移,命中区域就会出现反向偏移的问题。
另外原代码存在两个隐性隐患:
camera变量声明在mousemove事件绑定之后,初始化阶段触发鼠标事件时会引用到未初始化的变量intersectObjects未开启递归检测,无法命中GLTF模型组内部的子网格
修复方案
- 修正鼠标Y轴的NDC坐标计算逻辑,对Y轴结果做反向处理
- 调整变量声明顺序,将相机、渲染器等核心对象的声明移到事件绑定逻辑之前
- 开启射线检测的递归参数,支持检测组内嵌套对象
修正后的射线检测核心代码:
/******************************** Ray casting ********************************/ const raycaster = new THREE.Raycaster(); const clickMouse = new THREE.Vector2(); window.addEventListener("mousemove", (e) => { clickMouse.x = (e.clientX / window.innerWidth) * 2 - 1; // 修正Y轴计算,匹配NDC坐标系规则 clickMouse.y = 1 - (e.clientY / window.innerHeight) * 2; raycaster.setFromCamera(clickMouse, camera); // 第二个参数传true开启递归检测,覆盖组内嵌套对象 const intersects = raycaster.intersectObjects(scene.children, true); intersects.forEach((intersect) => { console.log(intersect.object.userData.name); }); });
注意:需要把camera的声明代码块移动到mousemove事件绑定之前,避免初始化阶段的引用错误。其余纹理、模型、控制器相关逻辑无需调整,修改后即可恢复正常的射线检测效果。
内容的提问来源于stack exchange,提问作者Mike
相关产品推荐
相关产品推荐

