重置ARKit坐标

6

我有一个简单的问题。如果我想开始一场游戏,并把棋盘放在我的面前:

gameBoard!.position = SCNVector3(0, 0, -0.6)

在我离开游戏并再次回来之前,这个方法是有效的。我是否可以将游戏棋盘放在镜头前面的确切位置或距离我0.6m的地方?我可能已经移动到另一个位置。


你需要把游戏棋盘放在距离相机0.6米的地方。可以重置相机或者根据相机的位置计算棋盘的位置。 - allenh
@AllenHumphreys 当这种情况发生时,我的应用程序会冻结。你有看到任何关于此的文档吗? - Jches
我的评论是基于使用SceneKit的经验,但我认为ARKit有一个非常类似于SceneKit的相机概念。 - allenh
@AllenHumphreys,你可以给我提供一段重置相机或位置的示例代码吗? - Lim Thye Chean
4个回答

9

如果您想重置ARSession,您需要暂停、删除所有节点,并通过重置跟踪和删除锚点来重新运行会话。

我创建了一个重置按钮,可以在我想要重置时使用它:

@IBAction func reset(_ sender: Any) {

    sceneView.session.pause()
    sceneView.scene.rootNode.enumerateChildNodes { (node, stop) in
        node.removeFromParentNode()
    }
    sceneView.session.run(configuration, options: [.resetTracking, .removeExistingAnchors])
}

或者将其放在您的会话中断功能中!

这似乎运行良好。我将重置放在UIApplicationWillEnterForeground通知中,因此每次用户返回时都会重置游戏板位置。 - Lim Thye Chean

2
您可以使用选项 resetTracking,在再次调用您的ARSessionrun时实现此功能。
例如:
if let configuration = sceneView.session.configuration {
    sceneView.session.run(configuration,
                          options: .resetTracking)
}

1

“这个程序在我离开游戏并再次回来之前是可以运行的。”

后台无法跟踪相机位置。每当您的应用程序进入后台且相机关闭时,您都会失去其位置,sessionWasInterrupted(_:) 将被调用。

当会话无法接收到相机或运动传感器数据时,会话将被中断。会话中断发生在相机捕获不可用的情况下,例如,当您的应用程序处于后台状态或存在多个前台应用程序,或者设备繁忙以至于无法处理运动传感器数据时。


你如何重置相机? - slimboy
@slimboy 你是什么意思?相机在应用从后台返回后会自动重置。 - Vasilii Muravev

1
重置ARKit框架中的ARSession非常容易:
class ViewController: UIViewController, ARSCNViewDelegate, ARSessionDelegate {

    @IBOutlet var arView: ARSCNView!
    @IBOutlet weak var sessionInfoLabel: UILabel!

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        let configuration = ARWorldTrackingConfiguration()
        configuration.planeDetection = [.horizontal, .vertical]
        arView.session.run(configuration)
        arView.session.delegate = self
    }
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        arView.session.pause()
    }
    func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
        guard let planeAnchor = anchor as? ARPlaneAnchor else { 
            return 
        }
        let plane = Plane(anchor: planeAnchor, in: arView)
        node.addChildNode(plane)
    }
    func sessionInterruptionEnded(_ session: ARSession) {
        resetSessionTracking()
        sessionInfoLabel.text = "ARSession's interruption has ended" 
    }
    private func resetSessionTracking() {
        let config = ARWorldTrackingConfiguration()
        config.planeDetection = [.vertical, .horizontal]
        arView.scene.rootNode.enumerateChildNodes { (childNode, _) in
            childNode.removeFromParentNode()
        }
        arView.session.run(config, options: [.removeExistingAnchors, 
                                             .resetTracking, ])
    }
}

希望这有所帮助。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接