ARKit Session Paused and Not Resuming

前端 未结 4 1338
小蘑菇
小蘑菇 2020-12-06 12:04

In my ARKit app I am presenting a modal window. When I close the modal and go back to the ARSCNView then I find out that the session is paused due to this code:

<         


        
相关标签:
4条回答
  • 2020-12-06 12:48

    I get that you have chosen an answer, and that answer is what is recommended by apple, you can restart the AR Session. You can't unpause/resume the Session though, because the device stops it's tracking once you're out of your controller presenting the ARSceneView and will stop keeping track of the position of your device relative to the objects you've placed in the scene.

    Anyway, I've managed to restart the session essentially by destroying all aspects of my session and rebuilding them them when my view reappears, or through a button press.

    I'll post some sample code here. It's in Objective-C cause my project was written in that, but it might help future people with the same question.

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

    These destroy methods are used when the view disappears. I am also restarting the AR Session on a button press, but it is not through these methods. It is as follows:

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

    Hope it helps.

    0 讨论(0)
  • 2020-12-06 12:48

    Here's an answer working with Swift 4.2 and iOS 12.

    To present UI defined in another view controller over your AR scene, create your view controller instance and set it's modalPresentationStyle property to .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)
    }
    

    Bonus tip:

    To make your overlay appear to slide up from the bottom like a drawer, set

    materialPicker.modalTransitionStyle = .coverVertical
    

    then constrain your views in your overlay view controller a comfortable height from the bottom and set the background color of the view controllers view to UIColor.clear.

    If you want to darken the AR view while your overlay is displayed you can set the background color to a black color with an opacity/alpha value of approximately 0.75.

    Something like this:

    self.view.backgroundColor = UIColor(red: 0.0, green: 0.0, blue: 0.0, alpha: 0.75)
    

    or in the storyboard:

    In the screenshot above I have a tableview pinned to the bottom and sides of the overlay view controllers view, and a height constraint of 300.

    When done this way you can still see the AR view behind the overlay view controller and the scene continues to render.

    0 讨论(0)
  • 2020-12-06 12:50

    I don't know if the iOS 11 GM Seed or XCode 9 GM Seed versions fixed this today however I can successfully resume a paused ARSCNview with code as in the original question.

    sceneView.session.run(sceneView.session.configuration!)
    
    0 讨论(0)
  • 2020-12-06 12:52

    Not sure why your session isn't resuming, but... this generally isn't a situation you want to be in anyway.

    Notice in the readme that ships with Apple's ARKit sample code (attached to the WWDC17 session on ARKit):

    Avoid interrupting the AR experience. If the user transitions to another fullscreen UI in your app, the AR view might not be an expected state when coming back.

    Use the popover presentation (even on iPhone) for auxiliary view controllers to keep the user in the AR experience while adjusting settings or making a modal selection. In this example, the SettingsViewController and VirtualObjectSelectionViewController classes use popover presentation.

    To go into a bit more detail: if you pause the session, it won't be tracking the world while your user is away in a different fullscreen view controller. That means that when you resume, any virtual content placed in the scene won't be in the positions (relative to the camera) where you left it.

    0 讨论(0)
提交回复
热议问题