私のARKitアプリでは、モーダルウィンドウを表示しています。モーダルを閉じてARSCNViewに戻ると、次のコードが原因でセッションが一時停止していることがわかります。
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)
}
}
セッションが再開されない理由はわかりませんが...これは通常、とにかくあなたが望んでいる状況ではありません。
AppleのARKitサンプルコード( ARKitのWWDC17セッション に添付)に付属しているreadmeに注意してください。
ARエクスペリエンスの中断を回避します。ユーザーがアプリで別のフルスクリーンUIに移行した場合、ARビューが戻ったときに予期された状態にならない可能性があります。
補助ビューコントローラーのポップオーバープレゼンテーション(iPhoneでも)を使用して、設定の調整やモーダル選択を行っている間、ユーザーがARエクスペリエンスを維持できるようにします。この例では、
SettingsViewController
クラスとVirtualObjectSelectionViewController
クラスはポップオーバー表示を使用しています。
もう少し詳しく説明すると、セッションを一時停止すると、ユーザーが別のフルスクリーンビューコントローラーにいる間、セッションは世界を追跡しなくなります。つまり、再開すると、シーンに配置された仮想コンテンツは、カメラを離れた位置に配置されなくなります。
IOS 11 GM SeedまたはXCode9 GM Seedのバージョンでこれが修正されたかどうかはわかりませんが、一時停止したARSCNviewを元のコードと同じように正常に再開できます。質問。
sceneView.session.run(sceneView.session.configuration!)
あなたが答えを選んだと思います、そしてその答えはアップルによって推奨されているものです、あなたは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];
}
これらのdestroyメソッドは、ビューが消えたときに使用されます。ボタンを押すだけで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];
}
それが役に立てば幸い。
Swift 4.2およびiOS12で動作する回答は次のとおりです。
別のビューコントローラーで定義されたUIをARシーンに表示するには、ビューコントローラーインスタンスを作成し、その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ビューを暗くしたい場合は、背景色を不透明度/アルファ値が約0.75の黒色に設定できます。
このようなもの:
self.view.backgroundColor = UIColor(red: 0.0, green: 0.0, blue: 0.0, alpha: 0.75)
またはストーリーボード内:
上のスクリーンショットでは、オーバーレイビューコントローラービューの下部と側面にテーブルビューが固定されており、高さの制約は300です。
このようにすると、オーバーレイビューコントローラーの背後にあるARビューを引き続き表示でき、シーンは引き続きレンダリングされます。