ARFoundationをさわってみた
今回は、 Unity 向けに ARKit と ARCore の機能をまとめた AR Foundation について調べました。
開発環境
・Unity 2019.1.1f1 (2019.1以降が推奨されています)
・AR Foundation 2.1.0
・ARCore XR Plugin 2.1.0
・ARKit XR Plugin 2.1.0
環境構築1.必要なパッケージをインストール
Unity2019.1では ARFoundation は preview となっているので、まず、Package Manager > Advanced で Show preview packages を選択して、一覧に表示します。
一覧の中から AR Foundation 、 ARCore XR Plugin 、 ARKit XR Plugin の3つをインストールしましょう。
環境構築2.Android の API レベルを変更
Project Settings > Player > Identification > Minimum API Level を 7.0以上に変更します。
環境構築3.Hierarchy に必要な GameObject を配置
はじめから置かれている Main Camera を削除します。
GameObject > XR > AR Session Origin と AR Session をヒエラルキーに配置します。
これで ARFoundation の開発環境が整いました😎
動かしてみる
ここからはサンプルプロジェクトのシーンを動かしながら、各機能を確認していきます。
動かしてみる1.平面を検出する
GameObject > XR > AR Default Plane を一旦ヒエラルキーに配置して、 Prefab 化します。Prefab 化したら、ヒエラルキーから削除しましょう。
AR Session Origin に AR Plane Managerコンポーネントを追加します。
次に、AR Plane Manager コンポーネントの Plane Plefab に Prefab 化した AR Default Plane を設定します。
この作業で、 Android ・ iOS 両方に対応した平面検出が実装できました。
実機にビルドして動かすとこんな感じです。
ここまで、コードを一切書かずに作ることができます。
・検出速度、精度共に ARKit 、 ARCore と同じくらいの性能です。
・iOS 上で動かす時のみ ARKit 同様、検出した平面が存在しない方向を向いた後に平面に向き直ると、平面の場所が大きくズレてしまう事があります。
動かしてみる2.平面にオブジェクトを置く
平面に向けて Ray を飛ばすために、 AR Session Origin に AR Raycast Managerコンポーネントを追加します。
var hits = new List<ARRaycastHit>();
if (_arRaycastManager.Raycast(touch.position, hits,TrackableType.PlaneWithinPolygon))
{
Pose pose = hits[0].pose;
// ここに生成、移動処理を書く
}
AR Raycast Managerコンポーネントの ARRaycastManager.Raycastメソッド で、平面に向けて Ray を飛ばして、 List<ARRaycastHit> を取得することができます。
ARRaycastHit から Pose を取得してオブジェクトを生成、移動させましょう。
出来上がったものがこちらです。
動かしてみる3.マーカー認識
AR Session Origin に AR Tracked Image Managerコンポーネント を追加します。
Project ビューで右クリック -> Create -> XR -> Reference Image Library を作成します。
Add Image ボタンをクリックして、項目を増やし、Reference Image Library に認識したいマーカー画像を設定する。
※ Specify Size を有効にし、 Physical Size(物理サイズ)を設定すると、認識の精度が上がります。
1.AR Tracked Image Managerコンポーネント に作成した Reference Image Library を設定する
検出したマーカーの位置に3D モデル等を表示したい場合は、 Tracked Image Prefab に任意の Prefab を設定してください。
1.ARTrackedImageManager.trackedImagesChanged に Event を登録する事で、 ARTrackedImagesChangedEventArgsクラス が取得できる
2.ARTrackedImagesChangedEventArgsクラス には、「新たに検出したマーカー」、「情報が更新されたマーカー」、「検出されなくなったマーカー」の情報 (ARTrackedImageクラス) が added 、 updated 、 removed にそれぞれ格納されている
ARTrackedImage クラス から取得した値をもとに3D モデル等の Scale を調整します。
Position 、 Rotation は AR Session Originコンポーネント が検出したマーカーに合わせて自動で調整しているようです。
移動するマーカーには対応していませんでした。
マーカーの移動後の再認識までの速度は iOS の方が早いようです。
動かしてみる4.顔認識
AR Session Origin に AR Face Managerコンポーネント を追加します。
AR Face Managerコンポーネント の Face Prefab に、顔に重ねて表示する Prefab を設定します。
・iOS 、 Android どちらも同じプロジェクトでビルド出来ますが、 Rig は ARKit と同様のものを取得しているので、 Android では顔の位置と向きのみのトラッキングとなり、 Rig は動きません。
・UnityEngine.XR.ARCore.ARCoreFaceSubsystem.GetRegionPose s関数 で、 ARKit の Rig を ARCore の Rig に変換する事が可能です。(変換可能なのは ARCore に定義されている額2点と鼻1点の合計3点のみ)
動かしてみる5.Environment Probes
AR Session Origin に AR Environment Probe Managerコンポーネント を追加します。
周囲の風景を写したい GameObject のマテリアルの Metallic 、 Smoothness を1に設定します。(この2つの値で見た目の調整ができます。)
ちなみに、iOS のみ対応です。
カメラに映った物を映し出すので、本来映らないものまで映り込んでしまうことに注意です。(赤枠で囲んだ部分に本来写らないはずのコップやキーボードが写っていることが確認できます。)
ARKit の同機能とほぼ同じです。
動かしてみる6.World Map
ARKit 、 ARCore 共に似たような機能はあるが AR Foundation では iOS のみ対応しています。
ARKitSessionSubsystem sessionSubsystem = (ARKitSessionSubsystem)m_ARSession.subsystem;
ARWorldMapRequest request = sessionSubsystem.GetARWorldMapAsync();
// World Map を取得
ARWorldMap worldMap = request.GetWorldMap();
// シリアライズ化
var data = worldMap.Serialize(Allocator.Temp);
UnityEngine.XR.ARKit.ARKitSessionSubsystem から WorldMap を取得し、シリアライズ化する事で、 AR 空間の情報を保存する事ができます。
// デシリアライズ
if (ARWorldMap.TryDeserialize(data, out worldMap))
{
data.Dispose();
}
// World Map を適用
sessionSubsystem.ApplyWorldMap(worldMap);
byte 配列で保存してある World Map をデシリアライズする事で、同じ AR 空間を再現する事ができます。
検出した平面や、生成した GameObject の位置、向き、大きさを再現する事ができています。
ロード用のメソッドを呼んでから、再現されるまで、3秒程かかります。
まとめ
Unity Technologies が作っているだけあって、 UnityEditor 上で簡単に AR が実装できました。
ただ、 ARFoundation を使用して iOS 向けに作ったプロジェクトを、そのまま Android 向けにビルドすると動作に差が生まれることがありそうです。
動作検証の際にはご注意を!
この記事が気に入ったらサポートをしてみませんか?