Ios 如果命中测试失败,则将平移手势传递给默认摄影机控制器

Ios 如果命中测试失败,则将平移手势传递给默认摄影机控制器,ios,swift,scenekit,Ios,Swift,Scenekit,我有一个SceneKitSCNView,我希望在其中附加一个平移手势识别器。这将执行一个hitTest,以确定用户是否触摸了我场景中的特定对象。但是,如果这个命中测试失败(用户没有特别触摸任何东西),那么我希望将该触摸传递到默认的相机控制器 目前,添加我自己的平移手势识别器似乎会覆盖默认的相机控制器,并阻止它工作 let scnView = SCNView() // Configure scnView with my geometry etc // ... let panGesture = U

我有一个SceneKit
SCNView
,我希望在其中附加一个平移手势识别器。这将执行一个
hitTest
,以确定用户是否触摸了我场景中的特定对象。但是,如果这个命中测试失败(用户没有特别触摸任何东西),那么我希望将该触摸传递到默认的相机控制器

目前,添加我自己的平移手势识别器似乎会覆盖默认的相机控制器,并阻止它工作

let scnView = SCNView()
// Configure scnView with my geometry etc
// ...

let panGesture = UIPanGestureRecognizer(target: context.coordinator,
                                             action: #selector(panned))
scnView.addGestureRecognizer(panGesture)
scnView.allowsCameraControl = true
目前,我的手势识别器是这样启动的:

@objc func panned(gesture: UIPanGestureRecognizer) {
            let sceneView : SCNView = gesture.view as! SCNView
            let point = gesture.location(in: sceneView)

            switch gesture.state {
            case .began:

                guard let hitNodeResult = sceneView.hitTest(point, options: [:]).first else { return }
                // Rather than just 'return' I suspect I want to do something here...

             // ....
}

最后有三件事帮我解决了这个问题:

1.同时处理两个平移手势 首先,我必须在自己的平移手势上添加手势识别器代理:

myPanGesture.delegate = self
使用这样的委托方法:

func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
    return true;
}
2.要求我们的平移动作在摄像机启动前失败 接下来,我找到了控制相机的内置平移手势识别器,并告诉它要求我的平移手势失败后才能正常工作:

let panGestures = scnView.gestureRecognizers!.filter { $0 is UIPanGestureRecognizer } as! [UIPanGestureRecognizer]
if (!panGestures.isEmpty) {
    let cameraPanGesture = panGestures.first!
    cameraPanGesture.require(toFail: myPanGesture)
}
3.将失败的命中测试视为手势识别器“失败”
然后,嘿,普雷斯托,它起作用了!现在,您可以通过平移远离场景中的对象来旋转场景,或者在单击对象时平移对象。

最后有三件事帮助我解决了这个问题:

1.同时处理两个平移手势 首先,我必须在自己的平移手势上添加手势识别器代理:

myPanGesture.delegate = self
使用这样的委托方法:

func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
    return true;
}
2.要求我们的平移动作在摄像机启动前失败 接下来,我找到了控制相机的内置平移手势识别器,并告诉它要求我的平移手势失败后才能正常工作:

let panGestures = scnView.gestureRecognizers!.filter { $0 is UIPanGestureRecognizer } as! [UIPanGestureRecognizer]
if (!panGestures.isEmpty) {
    let cameraPanGesture = panGestures.first!
    cameraPanGesture.require(toFail: myPanGesture)
}
3.将失败的命中测试视为手势识别器“失败”
然后,嘿,普雷斯托,它起作用了!现在,您可以通过平移远离场景中的对象来旋转场景,或者在点击对象时平移对象。

只是为了澄清@andygeer出色的解决方案中的所有代码可以放在哪里

class GameViewController: UIViewController, UIGestureRecognizerDelegate {

    override func viewDidLoad() {
        super.viewDidLoad()

        let scnView = SCNView()
        // Configure scnView with my geometry etc
        // ...

        let myPanGesture = UIPanGestureRecognizer(target: self,
                                                  action: #selector(panned))
        myPanGesture.delegate = self
        scnView.addGestureRecognizer(myPanGesture)
        scnView.allowsCameraControl = true

        let panGestures = scnView.gestureRecognizers!.filter { $0 is UIPanGestureRecognizer } as! [UIPanGestureRecognizer]
        if (!panGestures.isEmpty) {
            let cameraPanGesture = panGestures.first!
            cameraPanGesture.require(toFail: myPanGesture)
       }
    }

    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        return true
    }

    @objc func panned(gesture: UIPanGestureRecognizer) {
        let sceneView : SCNView = gesture.view as! SCNView
        let point = gesture.location(in: sceneView)

        switch gesture.state {
        case .began:
            guard let hitNodeResult = sceneView.hitTest(point, options: [:]).first else {
                // Cancel the gesture so that the camera pan kicks in
                gesture.state = .failed
                return
            }
            // .....
        }
    }
}

只是为了澄清@andygeer出色的解决方案中的所有代码可以放在哪里

class GameViewController: UIViewController, UIGestureRecognizerDelegate {

    override func viewDidLoad() {
        super.viewDidLoad()

        let scnView = SCNView()
        // Configure scnView with my geometry etc
        // ...

        let myPanGesture = UIPanGestureRecognizer(target: self,
                                                  action: #selector(panned))
        myPanGesture.delegate = self
        scnView.addGestureRecognizer(myPanGesture)
        scnView.allowsCameraControl = true

        let panGestures = scnView.gestureRecognizers!.filter { $0 is UIPanGestureRecognizer } as! [UIPanGestureRecognizer]
        if (!panGestures.isEmpty) {
            let cameraPanGesture = panGestures.first!
            cameraPanGesture.require(toFail: myPanGesture)
       }
    }

    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        return true
    }

    @objc func panned(gesture: UIPanGestureRecognizer) {
        let sceneView : SCNView = gesture.view as! SCNView
        let point = gesture.location(in: sceneView)

        switch gesture.state {
        case .began:
            guard let hitNodeResult = sceneView.hitTest(point, options: [:]).first else {
                // Cancel the gesture so that the camera pan kicks in
                gesture.state = .failed
                return
            }
            // .....
        }
    }
}

您在哪里添加了第2点代码?@PrashantTukadiya当我设置
myPanGesture
时,我的泛手势我指的是在这里的哪个函数中
func gestureRecognizer(_gestureRecognizer:UIGestureRecognizer,应该与其他gestureRecognizer:UIGestureRecognizer)->Bool{
?@PrashantTukadiya这是一个手势代表的方法。在我的“第1点”下我将其委托设置为“self”-因此您可以将其定义为创建手势的类上的一个方法。您可以轻松地将委托设置为您喜欢的任何其他对象,并将其定义为该对象上的一个方法,而不是添加了第2点代码?@PrashantTukadiya,因为我正在设置
myPanGesture
,我的泛指这里的操作
func GestureRecognitizer(uGestureRecognitizer:UIGestureRecognitizer,应该与其他GestureRecognitizer:UIGestureRecognitizer同时识别)->Bool{
?@PrashantTukadiya这是手势代理上的一个方法。在我的“点1”下我将其委托设置为“self”-因此您可以将其定义为创建手势的类上的方法。您可以轻松地将委托设置为您喜欢的任何其他对象,并将其定义为该类上的方法