はじめに
今回は、 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 の開発環境が整いました
動かしてみる
ここからはサンプルプロジェクトのシーンを動かしながら、各機能を確認していきます。
平面検出
平面を検出する

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 同様、検出した平面が存在しない方向を向いた後に平面に向き直ると、平面の場所が大きくズレてしまう事があります。
平面にオブジェクトを置く

平面に向けて 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 を取得してオブジェクトを生成、移動させる。
出来上がったものがコチラです。
マーカー認識
![]()
AR Session Origin に AR Tracked Image Managerコンポーネント を追加する。
![]()
Project ビューで右クリック -> Create -> XR -> Reference Image Library を作成する。
![]()
Add Image ボタンをクリックして、項目を増やし、Reference Image Library に認識したいマーカー画像を設定する。
※ Specify Size を有効にし、 Physical Size(物理サイズ)を設定すると、認識の精度が上がります。
![]()
AR Tracked Image Managerコンポーネント に作成したReference Image Libraryを設定する。
また、検出したマーカーの位置に3D モデル等を表示たい場合は、 Tracked Image Prefab に任意の Prefab を設定する。
ARTrackedImageManager.trackedImagesChangedに Event を登録する事で、ARTrackedImagesChangedEventArgsクラス が取得できる。ARTrackedImagesChangedEventArgsクラス には、「新たに検出したマーカー」、「情報が更新されたマーカー」、「検出されなくなったマーカー」の情報 (ARTrackedImageクラス) がadded、updated、removedにそれぞれ格納されている。
ARTrackedImageクラス から取得した値をもとに3D モデル等の Scale を調整する。
- Position 、 Rotation は
AR Session Originコンポーネント が検出したマーカーに合わせて自動で調整しているようです。
- 移動するマーカーには対応していませんでした。
- マーカーの移動後の再認識までの速度は iOS の方が早いようです。
顔認識
![]()
AR Session Origin に AR Face Managerコンポーネント を追加する。
AR Face Managerコンポーネント の Face Prefab に、顔に重ねて表示する Prefab を設定する。
- iOS 、 Android どちらも同じプロジェクトでビルド出来るが、 Rig は ARKit と同様のものを取得しているので、 Android では顔の位置と向きのみのトラッキングとなり、 Rig は動かない。
UnityEngine.XR.ARCore.ARCoreFaceSubsystem.GetRegionPoses関数 で、 ARKit の Rig を ARCore の Rig に変換する事が可能。(変換可能なのは ARCore に定義されている額2点と鼻1点の合計3点のみ)
Environment Probes

AR Session Origin に AR Environment Probe Managerコンポーネント を追加する。

周囲の風景を写したい GameObject のマテリアルの Metallic 、 Smoothness を1に設定する。(この2つの値で見た目の調整ができる)
- iOS のみ対応

- カメラに映った物を映し出すので、本来映らないものまで映り込んでしまう。
(赤枠で囲んだ部分に本来写らないはずのコップやキーボードが写っています。)
- ARKit の同機能とほぼ同じ。
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 向けにビルドすると動作に差が生まれることがありそうです。








