You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 14:02:15