I'm working on an app which first detect that there is a vertical plane, and after that, if the user touches the plane I add a SCNNode to the rootNode. After that, I want to detect if the user touches the node to do more things, but I'm not able to detect that tap, it just detects plane taps. Right now I've come back to this method:
@objc func tapped(sender: UITapGestureRecognizer) {
let sceneView = sender.view as! ARSCNView
let tapLocation = sender.location(in: sceneView)
let hitTest = sceneView.hitTest(tapLocation, types: .existingPlaneUsingExtent)
if !hitTest.isEmpty {
addItem(hitTestResult: hitTest.first!)
hideTip()
}
}
Which is the one that add a node when tapping on the plane, but now I want to detect when the node is tapped, I've used this code:
let sceneView = sender.view as! ARSCNView
let tapLocation = sender.location(in: sceneView)
let hitTouchTest = sceneView.hitTest(tapLocation)
if !hitTouchTest.isEmpty {
let results = hitTouchTest.first!
let node = results.node
}
And it enters the if, but the name of the node is always nil, and when I create the node adding it to the plane I give it a name... How can I detect that the node is tapped?
The problem with this solution is that you taking the first value of an array of nodes that been touched. I recommend to read next topic: https://developer.apple.com/documentation/scenekit/scnhittestoption
And solution that you can implement:
func registerGestureRecognizer() {
let tap = UITapGestureRecognizer(target: self, action: #selector(search))
self.sceneView.addGestureRecognizer(tap)
}
@objc func search(sender: UITapGestureRecognizer) {
let sceneView = sender.view as! ARSCNView
let location = sender.location(in: sceneView)
let results = sceneView.hitTest(location, options: [SCNHitTestOption.searchMode : 1])
guard sender.state == .began else { return }
for result in results.filter( { $0.node.name != nil }) {
if result.node.name == "Your node name" {
// do manipulations
}
}
}
P.S. This approach helps you to get specific node via its name. Hope it helps!