Ios 检测哪架飞机在arkit上被点击

Ios 检测哪架飞机在arkit上被点击,ios,scenekit,arkit,Ios,Scenekit,Arkit,我与ARKit合作,在一个场景中有几个planeNodes(SCNPlanes)。我想使用hittest来检测飞机上的触碰,但我不确定如何检测哪架飞机被窃听。每个平面都有一个与我的图像识别代码关联的名称。以下是我的ToucheSBegind功能: //detects taps on transparent planes created by reference images override func touchesBegan(_ touches: Set<UITouch>,

我与ARKit合作,在一个场景中有几个planeNodes(SCNPlanes)。我想使用hittest来检测飞机上的触碰,但我不确定如何检测哪架飞机被窃听。每个平面都有一个与我的图像识别代码关联的名称。以下是我的ToucheSBegind功能:

//detects taps on transparent planes created by reference images
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        let touch = touches.first as! UITouch
        if(touch.view == self.sceneView){
            let viewTouchLocation:CGPoint = touch.location(in: sceneView)
            guard let result = sceneView.hitTest(viewTouchLocation, options: nil).first else {
                return
            }
            print("results", "\(result)")
            let touchPlaneNode = planeNode
            if touchPlaneNode == result.node {
                print("tapped on a match, but which plane did I tap on?")
            }

        }
    }
//检测由参考图像创建的透明平面上的点击
覆盖func TouchesBegind(Touchs:Set,带有事件:UIEvent?){
让touch=touch.first as!UITouch
if(touch.view==self.sceneView){
让viewTouchLocation:CGPoint=touch.location(in:sceneView)
guard let result=sceneView.hitTest(viewTouchLocation,选项:nil)。首先{
返回
}
打印(“结果”,“结果”)
让touchPlaneNode=planeNode
如果touchPlaneNode==result.node{
打印(“点了一根火柴,但我点了哪架飞机?”)
}
}
}

谢谢

假设我正确地阅读了你的问题,一个好的开始方法是将ARPlaneAnchor及其关联的SCNNode存储在字典中,例如:

    var planes = [ARPlaneAnchor: PlaneNode]()
在我的例子中,“Plane Node”值是一个自定义SCNNode,但是您可以存储任何您喜欢的节点

然后将在以下ARSCNView委托方法中创建此引用:

 func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {

        //1. Check The We Have An ARPlane Anchor
        guard let planeAnchor = anchor as? ARPlaneAnchor else { return }

        //2. Create Our Plane Node
        let planeNode = PlaneNode(anchor: planeAnchor, node: node, image: true, identifier: planes.keys.count, opacity: 1)

        //3. Store A Reference To It
        planes[planeAnchor] = planeNode


}
然后在触摸开始时,您可以执行以下操作:

   override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {

    /*
     1. Get The Current Touch Location
     2. Check That We Have Touched A Valid Node
     3. Check That Our Touched Object Is An ARPlane Anchor
     4. Determine If It Is One That Has Been Stored
     5. Get It's Name
     */

    guard let touchLocation = touches.first?.location(in: augmentedRealityView),
        let hitTest = augmentedRealityView.hitTest(touchLocation, types: .existingPlaneUsingExtent).first,
        let planeAnchor = hitTest.anchor as? ARPlaneAnchor,
        let detectedPlane = self.planes[planeAnchor],
        let nodeID = detectedPlane.name
        else {
             //No Valid Plane Has Been Detected
            return

    }

    print(nodeID)


}

嘿,乔希,谢谢你的提示!我在定义平面的顶行出现了一个错误:
表达式的类型是不明确的,没有更多的上下文
任何想法?你的PlaneNode类是什么样子的?还有,只要你有第二个。我在控制台中遇到此错误:
当添加到视图时,约束项必须是该视图(或视图本身)的后代。如果在装配视图层次之前需要解决约束,则此操作将崩溃。中断-[UIView(UIConstraintBasedLayout)\u viewHierarchyUnpreparedForConstraint:]以进行调试。
这仅在根据代码进行更改后开始发生。你知道这个错误是指什么吗?再次感谢!这是在讨论Interface builder中的某些内容,或设置场景的方式。当我运行它时,我在控制台中没有发现任何问题:)好的,谢谢你缩小范围。我再看看我的代码。谢谢你,乔希!
class PlaneNode: SCNNode {

let DEFAULT_IMAGE: String = "defaultGrid"
let NAME: String = "PlaneNode"
var planeGeometry: SCNPlane
var planeAnchor: ARPlaneAnchor

var widthInfo: String!
var heightInfo: String!
var alignmentInfo: String!

//---------------
//MARK: LifeCycle
//---------------

/// Inititialization
///
/// - Parameters:
///   - anchor: ARPlaneAnchor
///   - node: SCNNode
///   - node: Bool
init(anchor: ARPlaneAnchor, node: SCNNode, image: Bool, identifier: Int, opacity: CGFloat = 0.25){

    self.planeAnchor = anchor

    self.planeGeometry = SCNPlane(width: CGFloat(anchor.extent.x), height: CGFloat(anchor.extent.z))
    let planeNode = SCNNode(geometry: planeGeometry)

    super.init()

    if image{

        let planeMaterial = SCNMaterial()
        planeMaterial.diffuse.contents = UIImage(named: DEFAULT_IMAGE)

        self.planeGeometry.materials = [planeMaterial]
    }

    planeNode.simdPosition = float3(self.planeAnchor.center.x, 0, self.planeAnchor.center.z)
    planeNode.eulerAngles.x = -.pi / 2
    planeNode.opacity = opacity

    node.addChildNode(planeNode)
    node.name = "\(NAME) \(identifier)"

}

required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") }

deinit {
    #if DEBUG
    print("Plane Node Deinitialized")
    #endif
}

/// Updates The Size Of The Plane As & When The ARPlaneAnchor Has Been Updated
///
/// - Parameter anchor: ARPlaneAnchor
func update(_ anchor: ARPlaneAnchor) {

    self.planeAnchor = anchor

    self.planeGeometry.width = CGFloat(anchor.extent.x)
    self.planeGeometry.height = CGFloat(anchor.extent.z)

    self.position = SCNVector3Make(anchor.center.x, 0.01, anchor.center.z)

    returnPlaneInfo()
}

//-----------------------
//MARK: Plane Information
//-----------------------

/// Returns The Size Of The ARPlaneAnchor & Its Alignment
func returnPlaneInfo(){

    let widthOfPlane = self.planeAnchor.extent.x
    let heightOfPlane = self.planeAnchor.extent.z

    var planeAlignment: String!

    switch planeAnchor.alignment {

    case .horizontal:
        planeAlignment = "Horizontal"
    case .vertical:
        planeAlignment = "Vertical"
    }

    #if DEBUG
    print("""
        Width Of Plane =  \(String(format: "%.2fm", widthOfPlane))
        Height Of Plane =  \(String(format: "%.2fm", heightOfPlane))
        Plane Alignment = \(planeAlignment)
        """)
    #endif

    self.widthInfo = String(format: "%.2fm", widthOfPlane)
    self.heightInfo = String(format: "%.2fm", heightOfPlane)
    self.alignmentInfo = planeAlignment
  }

}