Ios ARKit会话已暂停,无法继续

Ios ARKit会话已暂停,无法继续,ios,arkit,Ios,Arkit,在我的ARKit应用程序中,我演示了一个模式窗口。当我关闭模式并返回ARSCNView时,我发现会话因以下代码而暂停: override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) // Pause the view's session sceneView.session.pause() } 当我关闭模式并返回ARKit c

在我的ARKit应用程序中,我演示了一个模式窗口。当我关闭模式并返回ARSCNView时,我发现会话因以下代码而暂停:

 override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)

        // Pause the view's session
        sceneView.session.pause()
    } 
当我关闭模式并返回ARKit camera view屏幕时,会触发以下代码:

override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)

        // Create a session configuration
        let configuration = ARWorldTrackingSessionConfiguration()

        // Run the view's session
        sceneView.session.run(configuration)
    }
但此代码从不恢复会话。屏幕在最后读取的图像上完全冻结。有什么想法吗

我将viewdide代码更新为以下代码。它仍然停留在相机屏幕上,图像冻结

  override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)

        // Create a session configuration
        let configuration = ARWorldTrackingSessionConfiguration()

        sceneView.session.delegate = self

        if self.isPaused {
            sceneView.session.run(sceneView.session.configuration!)
        } else {
            // Run the view's session
            sceneView.session.run(configuration)
        }


    }

不确定您的会话为什么没有恢复,但是。。。这通常不是你想要的情况

请注意自述文件中随附的苹果ARKit示例代码(附于附件):

避免中断AR体验。如果用户切换到应用程序中的另一个全屏UI,则返回时AR视图可能不是预期状态

为辅助视图控制器使用popover演示(甚至在iPhone上),在调整设置或进行模式选择时让用户保持AR体验。在本例中,
SettingsViewController
VirtualObjectSelectionViewController
类使用popover表示


更详细地说:如果您暂停会话,当您的用户在不同的全屏视图控制器中时,它将不会跟踪世界。这意味着当你恢复时,场景中的任何虚拟内容都不会位于你离开它的位置(相对于相机)。

我知道你已经选择了一个答案,而这个答案是苹果公司推荐的,你可以重新启动AR会话。但是,您不能取消暂停/恢复会话,因为一旦您离开控制器,设备将停止跟踪,并显示ARSceneView,并且将停止跟踪设备相对于场景中放置的对象的位置

无论如何,我已经设法重新启动会话,基本上是通过销毁会话的所有方面,并在视图重新出现时重建它们,或者通过按下按钮

我将在这里发布一些示例代码。这是用Objective-C写的,因为我的项目就是用它写的,但它可能会帮助未来的人解决同样的问题

-(void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated]
    [self setupScene];
    [self setupSession];
}

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    [self destroySession];
    [self destroyScene];
}

- (void)setupScene {

// Setup the ARSCNViewDelegate - this gives us callbacks to handle new
// geometry creation
    self.sceneView.delegate = self;

// A dictionary of all the current planes being rendered in the scene
    self.planes = [NSMutableDictionary new];

// Contains a list of all the boxes rendered in the scene
    self.boxes = [NSMutableArray new];

// Show statistics such as fps and timing information
    self.sceneView.showsStatistics = YES;
    self.sceneView.autoenablesDefaultLighting = YES;

    SCNScene *scene = [SCNScene new];

    [self.sceneView setScene:scene];

    self.sceneView.scene.physicsWorld.contactDelegate = self;   
}

- (void)setupSession {

    // Create a session configuration
    ARWorldTrackingConfiguration *configuration = [ARWorldTrackingConfiguration new];
    //ARWorldTrackingSessionConfiguration *configuration = [ARWorldTrackingSessionConfiguration new]; This has been deprecated in favor of the previous line in XCode 9 beta 5. 

    // Specify that we do want to track horizontal planes. Setting this will cause the ARSCNViewDelegate
    // methods to be called when scenes are detected
    //configuration.planeDetection = ARPlaneDetectionHorizontal;

    // Run the view's session
    [self.sceneView.session runWithConfiguration:configuration options:ARSessionRunOptionResetTracking];
}


-(void)destroyScene {
    bottomPlane = nil;
    [self.sceneView setScene:nil];
    [self.sceneView setDebugOptions:nil];
    self.boxes = nil;
    self.planes = nil;
    self.sceneView.delegate = nil;  
}

-(void)destroySession {
    [self.sceneView.session pause];
    [self.sceneView setSession:nil];
}
这些销毁方法在视图消失时使用。我也通过按下按钮重新启动AR会话,但不是通过这些方法。详情如下:

-(void)resetPressed{
    NSLog(@"Reset Pressed");
    [_sceneView.session pause];


    SCNScene *scene = [[SCNScene alloc] init];
    [_sceneView setScene:scene];
    [_sceneView.scene.rootNode enumerateChildNodesUsingBlock:^(SCNNode * _Nonnull child, BOOL * _Nonnull stop) {
        [child removeFromParentNode];
    }];

    ARWorldTrackingConfiguration *configuration = [[ARWorldTrackingSessionConfiguration ARWorldTrackingConfiguration] init];
    [_sceneView.session runWithConfiguration:configuration options:ARSessionRunOptionResetTracking | ARSessionRunOptionRemoveExistingAnchors];
}

希望有帮助。

我不知道iOS 11 GM-Seed或XCode 9 GM-Seed版本今天是否解决了这个问题,但是我可以成功地恢复暂停的ARSCNview,代码与原始问题相同

sceneView.session.run(sceneView.session.configuration!)

以下是使用Swift 4.2和iOS 12的答案

要在AR场景上显示另一个视图控制器中定义的UI,请创建视图控制器实例,并将其
modalPresentationStyle
属性设置为
。overCurrentContext

EXAMPLE:

func showMaterialPicker(completion: (Texture?) -> Void) {

    // create an instance of your view controller, I have convenience functions
    // setup to do this via an extension on UIViewController
    guard let materialPicker = MaterialCategoriesViewController.instance(from: .product) else {
        print("Unable to instantiate MaterialCategoriesViewController, bailing")
        return
    }

    // set presentation style and transition style
    materialPicker.modalPresentationStyle = .overCurrentContext
    materialPicker.modalTransitionStyle = .crossDissolve

    // present the controller
    present(materialPicker, animated: true, completion: nil)
}
奖金提示:

要使覆盖层看起来像抽屉一样从底部向上滑动,请设置

materialPicker.modalTransitionStyle = .coverVertical
然后将覆盖视图控制器中的视图从底部约束到合适的高度,并将视图控制器视图的背景色设置为UIColor.clear

如果要在显示覆盖时使AR视图变暗,可以将背景色设置为黑色,不透明度/alpha值约为0.75

大概是这样的:

self.view.backgroundColor = UIColor(red: 0.0, green: 0.0, blue: 0.0, alpha: 0.75)
或者在故事板中:

在上面的屏幕截图中,我在叠加视图控制器视图的底部和侧面固定了一个tableview,高度限制为300


这样做后,您仍然可以看到叠加视图控制器后面的AR视图,场景继续渲染。

谢谢@rickster!现在有道理了。我会确保用户不会离开AR体验而使用popover演示文稿。即使在使用popover演示文稿时,我也会看到会话被冻结。可能的错误?被接受的答案还说,他们无法重现这个问题,并进一步详述。这个答案可以被编辑以增加OP和其他关于这个问题的人的价值吗?这对我来说非常有用!首先是self.sceneView.session.pause(),然后是sceneView.session.run(sceneView.session.configuration!),这就是我一直在做的事情。但不知何故,如果长时间丢失帧,则会创建环绕ARSession的第二次。摄像机状态无限期地停留在ARTrackingStateLimited。我不太明白你是如何处理世界中心坐标的变化的。最有可能的是,在你第二次主持会议时,世界将不在同一个中心。因此,所有加载的节点都将放错位置。你能为我提供一个解决这个问题的方法吗?因为我能想到的只是一些图像识别软件,它能以某种方式转换世界中心的变化,并从中给出一个转换矩阵。有更好的建议吗?@dvp.petrov我不是在讨论坐标的变化。我只是简单地解决了问题中的问题,即当OP返回到AR视图控制器时,AR会话被暂停并且没有移动。我只是提供了一种方法,一旦您返回到视图控制器,就可以重新启动会话。关于你的问题,我想你可以保存你添加的所有节点的位置,并在回来后重新添加它们,但不能保证设备在那一点上会处于相同的物理位置。@AlanS-我很好奇,你第二次运行ARSession时,它是否和第一次一样稳定?在我的第二次运行中,我将它永远作为ArtrackingStateReasonInitialization,并且它永远不会成为ARTrackingStateReasonNone。最后!两天后,我可以说,这就是成功的原因!事实上,我有一点不同的问题。当我在SceneViewController上显示一个NewViewController时,这个NewViewController冻结了。我尝试过暂停、恢复会话、完全删除场景并重新初始化ViewWillAppease,但没有任何效果。只有我是通过@di看到这篇文章的