ARKit session paused and not resumed

In my ARKit app, I present a modal window. When I close modal and go back to ARSCNView, then I know that the session is suspended due to this code:

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

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

      

When I close the modal and return to the ARKit camera view screen, this code runs:

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

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

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

      

But this code never resumes the session. The screen is completely frozen in the last image he reads. Any ideas?

I am updating the viewDidAppear code as follows. It is still stuck on the camera screen with a frozen image.

  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 session
            sceneView.session.run(configuration)
        }


    }

      

+8


source to share


4 answers


Not sure why your session is not resuming, but ... this is generally not the situation you want to be in anyway.

Note that in the readme that comes with the Apple ARKit sample code (attached to the WWDC17 session on ARKit ):



Avoid interrupting AR operation. If the user navigates to a different full screen UI in your application, the AR view might not be the expected state when returning.

Use presentation popover (even on iPhone) for auxiliary view controllers so the user can use AR when setting options or choosing modality. In this example, the classes SettingsViewController

and VirtualObjectSelectionViewController

use the presentation popover.

To go into more detail: if you pause a session, it won't track the world while your user is in another full screen view. This means that when you resume, any virtual content placed in the scene will not be in the positions (relative to the camera) where you left it.

+6


source


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



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

      

+3


source


I figured you chose the answer and this answer is what Apple recommends, you can restart your AR session. You cannot pause / resume the session because the device stops tracking it after you log out of your controller representing the ARSceneView and stops tracking the position of your device relative to the objects you placed in the scene.

Anyway, I managed to restart the session, essentially destroying all aspects of my session and restoring them when my view reappears or a button is clicked.

I'll post some sample code here. It's in Objective-C because my project was written in this, 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 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 destruction methods are used when the view disappears. I also restart my AR session on a button press, but this is not with these methods. It looks like this:

-(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.

+2


source


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

In order to present the user interface defined in another view controller above the AR scene, create a view controller instance and set its modalPresentationStyle

properties .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 an overlay on top like a drawer, slide down from the bottom, set

materialPicker.modalTransitionStyle = .coverVertical

      

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

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

Something like that:

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

      

or in a storyboard:

enter image description here

In the screenshot above, I have a table view attached to the bottom and sides of the overlay controllers view, and a height limit of 300.

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

0


source







All Articles