SceneKit:忽略前景SCNNode触摸,将触摸传递至背景节点
解决ARSCNView中忽略指定节点触摸的问题
方法1:禁用Node1的用户交互
最直接的方式是关闭Node1的用户交互,这样hitTest会自动跳过它,直接检测下层的Node2:
node1.isUserInteractionEnabled = false
这个方法无需额外处理hitTest结果,完全适配你需要忽略Node1触摸的场景。
方法2:过滤hitTest结果
如果Node1必须保留用户交互(比如有其他操作需求),可以在hitTest后手动过滤掉Node1及其子节点的结果,只保留Node2相关的:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { guard let touch = touches.first, let sceneView = view as? ARSCNView else { return } let touchLocation = touch.location(in: sceneView) let allResults = sceneView.hitTest(touchLocation, options: nil) // 筛选出属于Node2或其子节点的结果 let targetResults = allResults.filter { result in var currentNode = result.node // 向上遍历父节点,判断是否属于Node2分支 while let parent = currentNode.parent { if parent == node2 { return true } currentNode = parent } return currentNode == node2 } if let validResult = targetResults.first { // 处理Node2的触摸逻辑,比如获取测量数据 print("触摸到目标节点:\(validResult.node)") } }
方法3:使用Category Bit Mask控制检测范围
通过节点的categoryBitMask属性,限定hitTest只检测Node2的类别,从根源上排除Node1:
// 初始化节点时设置类别掩码 node1.categoryBitMask = 0b0001 // Node1的掩码 node2.categoryBitMask = 0b0010 // Node2的掩码 // 触摸时执行hitTest,只检测Node2的类别 override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { guard let touch = touches.first, let sceneView = view as? ARSCNView else { return } let touchLocation = touch.location(in: sceneView) let results = sceneView.hitTest(touchLocation, options: [ SCNHitTestOption.categoryBitMask: 0b0010 // 仅匹配Node2的掩码 ]) if let targetResult = results.first { // 处理测量逻辑 } }
优先推荐方法1,操作简单且性能最优;如果有特殊交互需求,再考虑方法2或3。
内容的提问来源于stack exchange,提问作者Chandana
相关产品推荐
相关产品推荐

