swiftxcodescenekituipangesturerecognizerscene

How to apply a UIPanGestureRecognizer to a scene without disturbing the orbit function?


Let's take the example scene which is generated when we build a new project in Xcode of type Game. It will show a rotating space ship. This object allows that the user turns it in all directions by a finger move. What I need here is to be able to recognize whether the user has started that type of movement with the 3D object. I added a UIPanGestureRecognizer to the scene view with the following code:

    let panGesture = UIPanGestureRecognizer(target: self, action: 
    #selector(handlePan(_:))) scnView.addGestureRecognizer(panGesture)
    
@objc
func handlePan(_ gestureRecognize: UIGestureRecognizer) {
      print("in handle Pan")
 }

This works in this respect that the message appears in the console when the finger moves. BUT the issue is now that the space ship does no longer react to this movement. Logical since the the UIPanGestureRecognizer captures the event. The question is now: What is the correct method to preserve on one hand the orbit function of the 3D model but get additionally a reaction to the pan gesture?


Solution

  • You can use hit testing on the SCNView (hit testing is actually part of SCNSceneRenderer) to determine if the start of the gesture is on any of the nodes you care about. You can use the category bit mask to narrow it down to nodes you care about.

    Do the hit testing in the gesture recogniser's delegate method, probably gestureRecognizerShouldBegin. Return false if the touch doesn't hit the thing you care about. This should allow you to interact with the node, while keeping the camera control if you aren't touching that node.

    You will need to implement shouldRecgonizeSimultaneouslyWith in the delegate as well, and return true so that the camera pan gesture is still handled.