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

ARKit开发:如何检测被点击的PlaneNode(SCNPlane)?

如何在ARKit中识别被点击的特定PlaneNode

嘿,这个场景我太熟了!之前做ARKit项目时也遇到过类似需求,给你分享下具体怎么实现👇

核心思路就是通过HitTest拿到触摸对应的平面锚点或节点,再结合你给每个PlaneNode设置的名称来精准识别。下面是分步的实现方案和代码示例:

核心步骤拆解

  • 先把屏幕触摸点转换成ARView能识别的坐标
  • 执行针对现有平面的HitTest,筛选出有效的平面结果
  • 从结果中关联到你的PlaneNode,读取你预设的名称

修改后的TouchesBegan函数(Swift示例)

假设你用的是Swift + ARKit,调整后的touchesBegan可以直接用:

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    super.touchesBegan(touches, with: event)
    
    // 先拿到触摸点和ARView实例
    guard let touch = touches.first, let arView = view as? ARView else { return }
    let touchLocation = touch.location(in: arView)
    
    // 执行HitTest,只检测已识别的平面(用existingPlaneUsingExtent精度更高)
    let hitResults = arView.hitTest(touchLocation, types: .existingPlaneUsingExtent)
    
    guard let targetResult = hitResults.first else {
        // 没点击到任何平面,直接返回
        return
    }
    
    // 方式1:通过锚点名称匹配你的PlaneNode
    if let targetPlane = arView.scene.rootNode.childNode(withName: targetResult.anchor.name, recursively: true) {
        print("你点击了:\(targetPlane.name ?? "未命名平面")")
        // 这里可以加点击后的逻辑,比如改变平面颜色
        targetPlane.geometry?.firstMaterial?.diffuse.contents = UIColor.systemBlue.withAlphaComponent(0.4)
    }
    
    // 方式2:如果你的PlaneNode是自定义子类(比如继承SCNNode),可以直接类型转换
    if let anchorNode = arView.node(for: targetResult.anchor), let customPlane = anchorNode as? PlaneNode {
        print("点击了自定义平面:\(customPlane.name ?? "未知")")
        // 执行自定义逻辑
        customPlane.handleTap()
    }
}

关键注意事项

  • 一定要给PlaneNode设置name:不管是直接给节点的name属性赋值,还是同步设置对应ARAnchor的name,这是识别的关键依据。
  • 选对HitTest类型:用existingPlaneUsingExtent会比existingPlane更精准,因为它会考虑平面的实际物理范围,减少误触到平面外区域的情况。
  • 自定义节点更方便:如果你的PlaneNode是自定义的子类(比如叫PlaneNode),直接类型转换能避免误匹配到其他无关节点,代码也更清晰。

内容的提问来源于stack exchange,提问作者ToxicProxy

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 09:18:35