Apple Engine

Apple, iPhone, iOS, その周辺のことについて

ARKit 3 で追加された ARCoachingOverlayView

f:id:x67x6fx74x6f:20190613002222p:plain

iOS 13 から ARKit に ARCoachingOverlayView が実装された。

ARCoachingOverlayView は AR でのセッション初期化中やリミテッドトラッキング状況で、ユーザーに視覚的な指示を表示する UI を提供する。
これまでは自力で実装していたものだが、iOS 13 では頑張ってつくらなくてもよい。

実装的には ARSCNView や ARView に ARCoachingOverlayView を addChild して delegate と各種設定をするだけ。

一応、UIView 継承し、親の View の最上部で表示されるため、ARSCNView や ARView ではなくても使用できる。
ただ、ARKit 用であり ARSession が必要なため ARKit の機能が必要になる。

お約束だが、現状はまだ Beta 版なので今後機能の追加、変更、削除される可能性があるので、その点は注意してほしい。

 

ARCoachingOverlayView のコーチング状態

f:id:x67x6fx74x6f:20190613002247p:plain

初期表示 (Phase 1 〜 3)

アプリを起動すると、ARKit はトラッキングを確立するため役立つコーチングオーバーレイが表示。
ユーザーへデバイスを移動するような表示が出る。

コーチングのゴール表示

平面を見つけるなどのコーチングのゴールを選択していると、 コーチングオーバーレイはそれに従って指示を変更する。

完了

平面認識など目標が達成され、それ以上コーチングが必要とされていないと判断した場合はコーチングオーバーレイが非表示になる。

再検出

ARKit の中断などで再度ワールドトラッキングの状態を回復させるなど、ARKit でリローカライズする必要がある場合、
コーチングオーバーレイはリローカライズを支援するようなユーザーをガイドするコーチングオーバーレイを表示する。

 

ARCoachingOverlayView の実装の流れ

以下を設定すると自動的にオーバーレイの UI が表示される。

  • ARCoachingOverlayView を初期化し、ARSCNView などから session を設定。
  • 平面認識など認識準備や完了で使用するゴールを設定する
  • デリゲートを設定する
  • 表示するビューへ ARCoachingOverlayView を addSubView する

デリゲートでは、ARCoachingOverlayView のアクティブになる前、非アクティブになった時、セッションがリセットされた時の関数が要されている。

 

ARCoachingOverlayView の API

ARCoachingOverlayView

クラスとクラスの使用とイニシャライズ

class ARCoachingOverlayView : UIView

 

goal

検知したい状態をゴールとして設定し、 コーチングオーバーレイがユーザーに指示する表示が決定される。

var goal: ARCoachingOverlayView.Goal { get set }

 

表示で設定できる ARCoachingOverlayView.Goal は以下のもので、 垂直/水平平面の両方、水平平面、トラッキング、垂直平面。

  • anyPlane
  • horizontalPlane
  • tracking
  • verticalPlane
enum Goal : Int

 

session

コーチングを表示するために使用するセッション。
ARSession が更新された場合、このプロパティが使用されセッションからコーチングビューも表示される。

var session: ARSession? { get set }

 

sessionProvider でセッションのデータソースをアクセスできるが、多分直接アクセスすることはあまりないと思う。

@IBOutlet weak var sessionProvider: ARSessionProviding? { get set }

 

delegate

コーチングイベントのコールバックを設定を実装する。

@IBOutlet weak var delegate: ARCoachingOverlayViewDelegate? { get set }

 

ARCoachingOverlayViewDelegate のプロトコルは以下の3つで、
アクティブになる前、非アクティブになった時、セッションがリセットされた時に設定する。

func coachingOverlayViewWillActivate(ARCoachingOverlayView)

func coachingOverlayViewDidDeactivate(ARCoachingOverlayView)

func coachingOverlayViewDidRequestSessionReset(ARCoachingOverlayView)

 

activatesAutomatically

現在のセッション状態に応じて、コーチングビューが自動的にアクティブにするかどうか設定するフラグ。

このフラグ有効になっている場合は、 セッションが初期化されてた時、またはトラッキング条件が特定のしきい値を低下している場合、コーチングオーバーレイがアクティブになり表示される。

デフォルトは true。 false の場合は isActive で調べ、setActive(_:animated:) を使用してマニュアルで非表示にする。

var activatesAutomatically: Bool { get set }

 

isActive

コーチングが行われているかどうかを示すフラグ。
activatesAutomatically が有効な場合、このフラグは自動で変化する。

var isActive: Bool { get set }

 

setActive(_:animated:)

コーチングを行う否かを制御する。

func setActive(_ active: Bool, 
      animated: Bool)

 

サンプルプロジェクトから実装方法を学ぶ

Placing Objects and Handling 3D Interaction のサンプルは以前あったものを ARKit 3 用に若干修正したもの。

ARCoachingOverlayView の実装されているのでこちらを見ながら説明をしてみる。

 

実装概要

このプロジェクトで ARCoachingOverlayView が使用されているのは、ViewController+CoachingOverlay.swift 。

この Swift ファイルは Storyboard で initail View Controller となる ViewController クラスのエクステンションで、ARCoachingOverlayViewDelegate プロトコルを使用し delegete を読み込んでいる。

 

ViewController+CoachingOverlay.swift

このファイルで設定されていないもの
  • coachingOverlay は ARCoachingOverlayView
  • sceneView は ARSCNView
  • upperControlsView は sceneView の上に配置されているボタンの UI(仮想オブジェクトを選択するボタン)
  • restartExperience は別の swift ファイルで実装されている AR のリセット処理

 

初期設定

ARKit をインポートし、ARCoachingOverlayViewDelegate を設定する。

import UIKit
import ARKit

extension ViewController: ARCoachingOverlayViewDelegate {
    ...
}

 

デリゲート

coachingOverlayViewWillActivate は ARCoachingOverlayView がアクティブになる前に実行される。

ARCoachingOverlayView が sceneView に表示されるため、その上にある UI である upperControlsView を非表示にする。

func coachingOverlayViewWillActivate(_ coachingOverlayView: ARCoachingOverlayView) {
    upperControlsView.isHidden = true
}

 

coachingOverlayViewDidDeactivate は ARCoachingOverlayView が非アクティブになった時に実行される。

AR が使用できる状況になるため、使用する UI である upperControlsView を表示する。

func coachingOverlayViewDidDeactivate(_ coachingOverlayView: ARCoachingOverlayView) {
    upperControlsView.isHidden = false
}

 

coachingOverlayViewDidRequestSessionReset はセッションがリセットされた時に実行される。

ここでは restartExperience() が呼ばれ AR の状態がリセットされ、その後 coachingOverlayViewWillActivate が呼ばれる

func coachingOverlayViewDidRequestSessionReset(_ coachingOverlayView: ARCoachingOverlayView) {
    restartExperience()
}

 

メインで呼ばれる関数

setupCoachingOverlay() は ViewController の viewDidLoad() で呼ばれため、この関数はアプリ実行時に呼ばれる。

coachingOverlay.session で sceneView.session を渡し、
coachingOverlay.delegate で ViewController の self を渡す。
その後各関数を呼ぶ。

(わかりやすくするため、元のコードから Auto Layout のコンストレイントの記述は省略している)

func setupCoachingOverlay() {
    coachingOverlay.session = sceneView.session
    coachingOverlay.delegate = self

    setActivatesAutomatically()
    setGoal()
}

 

activatesAutomatically で true に設定している。 デフォルトで true なので明示的に設定している理由は不明。

func setActivatesAutomatically() {
    coachingOverlay.activatesAutomatically = true
}

 

平面認識を行うため goal で .horizontalPlane を指定し、 平面認識を促す UI を表示する様に設定する。

func setGoal() {
    coachingOverlay.goal = .horizontalPlane
}

 

まとめ

そもそも ARCoachingOverlayView クラス自体の機能があまりないため、デリゲートを含めても書く部分は少ない。

認識やトラッキングを行う場合、この様な UI の実装を必ずする必要があるので、iOS 13 からはこちらを使用してみるのも良いかもしれない。