2017-07-07 68 views
5

在我ARKit应用程序我提出一个模态窗口。当我关闭模式,并回到ARSCNView然后我发现,本次会议暂停由于此代码:ARKit会议暂停,当前未恢复

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

     // Pause the view's session 
     sceneView.session.pause() 
    } 

当我关闭模式,并返回到ARKit摄像机视图画面这段代码被炒鱿鱼:

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

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

     // Run the view's session 
     sceneView.session.run(configuration) 
    } 

但是这段代码永远不会恢复会话。屏幕在读取的最后一张图像上完全冻结。有任何想法吗?

我更新viewDidAppear代码为以下。它仍然卡在相机屏幕上,冻结图像。

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) 
     } 


    } 

回答

5

不知道为什么你的会议不恢复,但是......这通常不是你想要的情况。在船舶与苹果的ARKit示例代码(附加到WWDC17 session on ARKit)自述

注意:

避免中断的AR体验。如果用户转换到在你的应用程序全屏另一个UI,在AR视图可能不会再回来的时候是一个预期的状态。

使用辅助视图控制器的弹出窗口演示文稿(甚至在iPhone上)可以在调整设置或进行模式选择时使用户保持AR体验。在这个例子中,SettingsViewControllerVirtualObjectSelectionViewController类使用酥料饼的介绍。

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

+0

感谢@rickster!现在有道理。我会确保用户不会离开AR体验并使用popover演示文稿。 –

+0

即使使用popover演示文稿,我仍然看到会话冻结。可能的错误? https://forums.developer.apple.com/thread/81943 –

1

我得知你已经选择了一个答案,并且这个答案是苹果推荐的,你可以重新启动AR Session。你无法取消暂停/恢复,虽然在会议上,由于设备停止它的跟踪,一旦你出你的控制器呈现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 Session,但它不是通过这些方法。这是因为如下:

-(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]; 
} 

希望它能帮助。

+0

这是我一直在做的事情。但不知何故,如果长时间保持丢失帧,将会创建ARSession的第二次。相机状态将无限期地保留在ARTrackingStateLimited处。 – nishant

+0

我不太明白你是如何解决协调世界中心的变化。第二次运行会话时,世界很可能不会在同一个中心。因此所有加载的节点都将错位。你能否为我提供这个问题的解决方案,因为我所能想到的只是一些ImageRecognition软件,它可以以某种方式翻译世界中心的变化,并从那里给出一个翻译矩阵。有更好的建议吗? –

+0

@ dvp.petrov我没有解决坐标的变化。我只是解决这个问题,这是当OP返回给AR - 视图 - 控制器的AR会议暂停和不动的问题。我只是提供重新启动会话的方法,一旦你回到视图控制器。 关于您的问题,我想您可以保存您添加的所有节点的位置,并在您回来后重新添加它们,但不能保证该设备将处于相同的物理位置点。 –

1

我不知道是否iOS 11 GM种子或XCode 9 GM种子版本今天解决了这个问题,但是我可以用原始问题中的代码成功恢复暂停的ARSCNview。

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

接受的答案也说,他们无法重现该问题,并进入更多细节。是否可以编辑此答案,以便为OP和其他问题增加价值? – stealththeninja

+0

这对我很好!首先self.sceneView.session.pause(),然后sceneView.session.run(sceneView.session.configuration!) – Jordan