1. 概要
ARCore は、スマートフォンで拡張現実エクスペリエンスを構築するための Google のフレームワークです。Unity の AR Foundation を使用して、クロス プラットフォームの AR アプリを作成できます。
作成するアプリの概要
この Codelab では、AR Foundation を使用して簡単なゲームを作成します。このゲームの目的は、ハンドヘルド デバイスで操作する車を使って荷物を回収することです。
しかし、これは完全な仮想世界では起こりません。プレーヤーの周囲の環境を理解するゲームを作成することで、物理原子とデジタルビットを組み合わせ、新しいタイプのプレーヤー エクスペリエンスを生み出します。
この Codelab を終了する時点で、ゲームは次のことができるようになります。
- 実世界の平面を検出し、その上にプレイグラウンドを描画します。
 - カメラのビューからレイを投影し、平面との交差を検出します。
 - 現実の照明条件に反応して、ゲームにリアルさを加えます。
 

学習内容
- Unity の AR Foundation を使用するプロジェクトを設定する方法。
 ARPlaneManagerを使用して新しい飛行機をサブスクライブする方法。Raycastを使用して仮想ジオメトリとの交差点を見つける方法ARLightEstimationDataを使用してシーンを照明する方法。
必要なもの
- USB ケーブルを使用して開発マシンに接続されたサポートされている ARCore デバイス。
 - Google Play 開発者サービス(AR) 1.23 以降。
 - Unity Hub または Unity 2020 LTS がインストールされていること。
 
2. 開発環境を設定する
このステップでは、Unity の AR Foundation で開発するための環境を準備します。
デバイスが AR に対応していることを確認してください
Android デバイスの AR エクスペリエンスは、ARCore 対応デバイスで利用可能な ARCore によって駆動されます。開発用デバイスが AR に対応していることを確認します。または、正しく構成された AR 対応の Android Emulator インスタンスを使用することもできます。
デバイスで USB デバッグを設定する
デバッグアプリを実行するには、デバイスで開発者向けオプションを有効にする必要があります。まだ有効にしていない場合は、Android のドキュメントで開発者向けオプションと USB デバッグを有効にする方法をご覧ください。
Unity(2020.3 LTS)をインストールする
ワークステーションに Unity 2020 LTS をインストールします。この Codelab では、2020.3(LTS)バージョンの Unity の UI のスクリーンショットを使用しています。他のバージョンの Unity も動作する場合もありますが、追加の手順が必要になる場合があります。表示される画面は、ここで示しているスクリーンショットとは異なる場合があります。
新しいプロジェクトを作成
Universal Render Pipeline テンプレートを使用して新しいプロジェクトを作成します。わかりやすい名前と適切な場所を指定して、[CREATE] をクリックします。

必要なフレームワークをインストールする
Unity の AR Foundation は、Unity Package Manager にあります。
- [Window] > [Package Manager] をクリックして開きます。
 

- このウィンドウで、この Codelab で使用するパッケージをインストールします。これらのフレームワークの最新バージョンを表示するには、
►アイコンを使用してエントリを展開します。以下の各フレームワークの最新バージョンをインストールします。- AR Foundation
 - ARCore XR プラグイン
 
 
完了すると、パッケージ マネージャーは次のようになります。

スターター パッケージをインストールする
この Codelab では、AR Foundation の使用方法に集中できるように、Codelab の一部を迅速に処理できるプレハブとスクリプトを含むスターター パッケージを用意しています。
- スターター パッケージをインストールするには、[Assets] > [Import Package] > [Custom Package...] を開き、
starter-package.unitypackageを開きます。 - ポップアップ ウィンドウで、すべての項目が選択されていることを確認します。
 - [インポート] をクリックします。
 
ビルド設定を変更する
アプリケーションは Android で実行されるため、ビルド プラットフォームを Android に変更します。
- [File] > [Build Settings] を開きます。
 - [Platform] ペインで [Android] を選択します。
 - 必要に応じて、開発ビルドとスクリプト デバッグを有効にして、アプリの実行中にデバッグ情報を保持します。
 - [Switch Platform] をクリックします。
 

プロジェクトの設定を変更する
起動時に XR システムを初期化するように AR Foundation を構成する必要があります。
- [Edit] > [Project Settings] を開き、[XR Plug-in Management] セクションをクリックします。
 - [Android] タブで [ARCore] を有効にします。
 

- 左側のペインで [プレーヤー] セクションをクリックします。
 - [Android] タブの [Other Settings] で、[Graphics APIs] から [Vulkan] を削除します。
 

- ARCore を使用する AR 必須アプリの最小 API レベルは 24 です。下にスクロールして [最小 API レベル] を見つけます。最小 API レベルを 24 に設定します。
 

必要なシーン要素を追加する
Universal Render Pipeline テンプレートには、このチュートリアルでは使用しないゲーム オブジェクトがいくつか含まれています。
SampleScene内のすべてのゲーム オブジェクトを削除します。

- AR Foundation オブジェクトを追加する。[Hierarchy] ペインを右クリックします。このメニューを使用して以下を追加できます。
 
- XR > AR セッション: このオブジェクトは、AR エクスペリエンスのライフサイクルを制御します。
 - XR >AR Session Origin: このオブジェクトは AR 座標を Unity ワールド座標に変換します。
 - 浅い睡眠 >ディレクショナル ライト: ゲーム オブジェクトを照明するための光源を提供します。
 
階層は次のようになります。

- 階層で作成した AR Session Origin を開き、AR Camera オブジェクトを選択します。インスペクタで、タグを [MainCamera] に変更します。
 

レンダリングを設定する
Unity の Universal Render Pipeline で AR Foundation に対応するには、1 つの変更が必要です。
- [Project] ペインで、[Assets] > [Settings] に移動して、ForwardRenderer アセットを見つけます。
 

- [ForwardRenderer] を選択します。
 - [Inspector] ペインで [Add Renderer Feature] を使用して、[AR Background Renderer Feature] を追加します。このコンポーネントは、シーンにカメラフィードをレンダリングします。
 

設定を確認する
- デバイスが電源に接続されていて、ADB デバッグがオンになっていることを確認してください。
 - [File] > [Build And Run...] をクリックします。これにより、アプリケーションがデバイスにアップロードされ、インストールが完了すると起動されます。
 - デバイスの画面にカメラフィードが表示されます。
 
次のステップでは、アプリに機能を追加します。
3. 現実世界の平面を検出する
基本的なシーンの設定が完了したら、ゲームの開発を開始します。このステップでは、平面を検出してシーンに描画します。
ARPlaneManager コンポーネントを追加する
ARPlaneManager は ARPlane を検出し、デバイスの環境に対する認識が変化したときにゲーム オブジェクトを作成、更新、削除します。
- [Hierarchy] ペインを使用して、空の 
GameObjectを作成します。 - 名前を 
Driving Surface Managerに変更します。このコンポーネントは、プレーヤーによって選択されるまでプレーンを表示します。 - 新しいゲーム オブジェクトを選択します。[Inspector] ペインで [Add Component] をクリックして [AR Plane Manager] を追加します。
 

Plane Prefabフィールドを設定して、ARPlaneManagerを構成します。Noneの横にあるボタンをクリックすると、[Select GameObject] ウィンドウが表示されます。- [アセット] タブを選択し、[Driving Surface Plane] を検索します。
 

スターター パッケージのこの Prefab は、飛行機のデコレーションとして使用されるざらざらした床のテクスチャを提供します。
Detection ModeをHorizontalに変更します。これにより、運転に最適な水平面のみを提供するようにARPlaneManagerが構成されます。
ARRaycastManager コンポーネントを追加する
ARRaycastManager はレイキャストの機能を公開します。次のステップでは、このオブジェクトを使用してユーザーにコントロールを提供します。
- [Hierarchy] ペインで 
Driving Surface Managerというオブジェクトが選択されていることを確認します。 - [Inspector] で [Add Component] をクリックして、ゲーム オブジェクトに 
ARRaycastManagerコンポーネントを追加します。 
このコンポーネントに必要な構成はありません。
DrivingSurfaceManager コンポーネントを追加する
DrivingSurfaceManager は、スターター パッケージのヘルパー スクリプトであり、ARPlane を選択できるようにします。ARPlane を選択すると、他のすべてのプレーンは非表示になり、新しいプレーンは無効になります。
- [Hierarchy] ペインで 
Driving Surface Managerというオブジェクトが選択されていることを確認します。 - Inspector で [Add Component] をクリックして、ゲーム オブジェクトに 
DrivingSurfaceManagerコンポーネントを追加します。 
このコンポーネントに必要な構成はありません。
アプリを実行する
- [ファイル] >Build And Run... を選択して、変更をテストします。
 - デバイスを水平な現実世界のサーフェスに向け、デバイスを動かして、ARCore による環境の把握を改善します。
 

- ARCore が平面を検出すると、現実世界の表面を覆うテクスチャが表示されます。
ARPlaneManagerは、検出されたプレーンごとに指定されたPlane Prefabをインスタンス化します。Driving Surface Planeプレハブには、特定のARPlaneのメッシュを作成するARPlaneMeshVisualizerコンポーネントが含まれています。 
次のステップでは、検出された平面を競技場として使用します。
4. 検出された平面に対してヒットテストを実行する
前のステップでは、平面を検出できるアプリをプログラムしました。これらの平面がゲームのシーンに反映されます。次に、平面を狙う照準レチクルと、検出された平面の上を走行する車を作成して、平面とのインタラクティビティを追加します。
照準レチクルを作成する
このアプリの操作方法では、プレーヤーがスマートフォンをサーフェスに向けて操作します。指定された場所を視覚的に明確に示すため、照準線を使用します。

このレチクルを AR プレーンに「貼り付ける」には、ヒットテストを使用します。ヒットテストは、特定の方向にレイを投影するときに交差点を計算する手法です。ヒットテストを使用して、カメラの画角の交差点を検出します。

レチクルを追加する
- 画面下部の [Project] ペインで、[Assets > Starter Package] に移動します。
 - プロジェクトの [Hierarchy] ペインに [Reticle Prefab] をドラッグしてシーンに配置します。
 - 階層内のレチクルを選択します。
 - インスペクタで [Add Component] をクリックします。スターター パッケージから 
ReticleBehaviourスクリプトを追加します。このスクリプトには、レチクルを制御するためのボイラープレートが含まれています。 ReticleBehaviourスクリプトは、前に作成したDriving Surface Managerに依存しているため、Driving Surface Manager選択ツールをクリックして依存関係を追加します。[シーン] タブを選択してDriving Surface Managerを選択します。

ReticleBehaviour を編集する
ReticleBehavior スクリプトにより、デバイスのビューポートの中央にあるプレーンにレチクルが配置されます。
ScriptフィールドをダブルクリックしてReticleBehaviour.csスクリプトを開きます。- カメラの 
ViewToScreenPointを使用して、画面の中心を決定します。Update()メソッドを編集して、次のように追加します。 
var screenCenter = Camera.main.ViewportToScreenPoint(new Vector3(0.5f, 0.5f));
- このポイントを使用してレイキャストを実行します。次のものを追加します。
 
var hits = new List<ARRaycastHit>();
DrivingSurfaceManager.RaycastManager.Raycast(screenCenter, hits, TrackableType.PlaneWithinBounds);
変数 hits には、ray で交差する追跡対象上の点を表す ARRaycastHit が含まれます。
hitsリストをクエリして、対象の交差点を特定します。DrivingSurfaceManagerに含まれるロックされたプレーンを優先します。存在しない場合は、最初にヒットしたプレーンを使用します。Update()の末尾に次のように追加します。
CurrentPlane = null;
ARRaycastHit? hit = null;
if (hits.Length > 0)
{
    // If you don't have a locked plane already...
    var lockedPlane = DrivingSurfaceManager.LockedPlane;
    hit = lockedPlane == null
        // ... use the first hit in `hits`.
        ? hits[0]
        // Otherwise use the locked plane, if it's there.
        : hits.SingleOrDefault(x => x.trackableId == lockedPlane.trackableId);
}
hitに結果が含まれている場合は、このGameObjectの変換をヒット位置に移動します。
if (hit.HasValue)
{
    CurrentPlane = DrivingSurfaceManager.PlaneManager.GetPlane(hit.Value.trackableId);
    // Move this reticle to the location of the hit.
    transform.position = hit.Value.pose.position;
}
Child.SetActive(CurrentPlane != null);
レチクルをテストする
- [File] > [Build And Run...] をクリックして、変更内容をテストします。
 - デバイスを平面に向けると、レチクルがカメラの動きに追随するのを確認できます。
 

車を作成する
プレイヤーはおもちゃの車を操作し、レチクルの位置に向かって走らせます。この車のモデルと動作は、スターター パッケージに用意されています。
シーンに CarManager を追加する
- [階層] で、新しい空の 
GameObjectを作成します。 - 名前を 
Car Spawnerに変更します。 - 作成したオブジェクトを選択します。[Hierarchy] ペインで [Add Component] をクリックして 
CarManagerコンポーネントを追加します。 - 各フィールドの選択ツールをクリックして、
CarManagerの依存関係を設定します。- Car Prefab: [Assets] で [Car Prefab] を選択します。
 - レチクル: [シーン] で [レチクル プレハブ] を選択します。
 - Driving Surface Manager: [Scene] で [Driving Surface Manager] を選択します。
 
 
この CarManager の動作では、レチクルが配置されている平面上におもちゃの車がスポーンされます。必要に応じて、CarBehaviour スクリプトを参照して、自動車のプログラムの仕組みを確認してください。
試乗
- [File] > [Build and Run] をクリックして、変更内容をテストします。
 - 飛行機をタップすると、その場所に小さな車が表示されます。この車はレチクルに沿って移動します。
 
ゲーム要素を追加する
プレーヤーがシーン内のエンティティを操作できるようになったので、プレーヤーが運転する目的地を設定します。
- 階層に新しい空の 
GameObjectを作成します。 - 名前を 
Package Spawnerに変更します。 - 作成したオブジェクトを選択します。[Hierarchy] ペインで [Add Component] をクリックして 
PackageSpawnerコンポーネントを追加します。 - 各フィールドの選択ツールをクリックして、
PackageSpawnerの依存関係を設定します。- Package Prefab: [Assets] で [Package Prefab] を選択します。
 - Driving Surface Manager [シーン] で [Driving Surface Manager] を選択します。
 
 
この PackageSpawner の動作は、まだパッケージがない場合に、ロックされた ARPlane のランダムな場所に新しいパッケージを生成します。
ゲームをテストする
- [File] > [Build and Run] をクリックして、変更内容をテストします。2. 車を作成すると、パッケージがスポーンします。
 - 車で荷物まで移動します。
 - 新しいアイコンがランダムな場所に表示されます。
 

5. 照明予測の設定
基本的なゲームが完成したので、AR シーンにリアルな雰囲気を加えましょう。このステップでは、ARCore の Lighting Estimation API を使用して、入力されるカメラフレームに基づいて現実世界に存在する照明を検出します。この情報を使用して、シーンのライティングを実際のライトに合わせて調整します。
照明の推定を有効にする
- [Hierarchy] で [AR Session Origin] を開き、[AR Camera] オブジェクトを選択します。
 - [Inspector] で、[AR Camera Manager] スクリプトを展開します。
 - [照明の推定] フィールドを [すべて] に変更します。
 

指向性ライトを変更する
- [Hierarchy] で、[Directional Light] オブジェクトを選択します。
 LightEstimationコンポーネントを追加します。スターター パッケージのこのコンポーネントには、照明の変化を定期購読するためのボイラープレートが用意されています。FrameReceived()関数に以下を追加します。
ARLightEstimationData lightEstimation = args.lightEstimation;
if (lightEstimation.averageBrightness.HasValue)
    Light.intensity = lightEstimation.averageBrightness.Value;
if (lightEstimation.averageColorTemperature.HasValue)
    Light.colorTemperature = lightEstimation.averageColorTemperature.Value;
if (lightEstimation.colorCorrection.HasValue)
    Light.color = lightEstimation.colorCorrection.Value;
if (lightEstimation.mainLightDirection.HasValue)
    Light.transform.rotation = Quaternion.LookRotation(lightEstimation.mainLightDirection.Value);
if (lightEstimation.mainLightColor.HasValue)
    Light.color = lightEstimation.mainLightColor.Value;
if (lightEstimation.mainLightIntensityLumens.HasValue)
    Light.intensity = lightEstimation.averageMainLightBrightness.Value;
if (lightEstimation.ambientSphericalHarmonics.HasValue)
{
    RenderSettings.ambientMode = AmbientMode.Skybox;
    RenderSettings.ambientProbe = lightEstimation.ambientSphericalHarmonics.Value;
}
変更のテスト
- [File] > [Build and Run] をクリックして、変更内容をテストします。
 - シーン内のオブジェクトを見ると、環境の照明に応じて色が付いていることがわかります。
 - 可能であれば、照明を変更してみてください。たとえば、現在いる部屋の照明を消してみてください。オブジェクトのライトが、実際のライトの変化に適応することがわかります。
 

6. まとめ
これで完了です。Unity AR Foundation に関するこの Codelab は終了しました。
学習した内容
- Unity の AR Foundation と Universal Rendering Pipeline を使用して基本的なプロジェクトを設定する方法。
 ARPlaneManagerを使用して新しいプレーンに登録する方法。Raycastを使用して仮想ジオメトリとの交差を見つける方法。ARLightEstimationDataを使用してシーンを照らす方法。
次のステップ
- Unity の AR Foundation のサンプルをご覧ください。
 - AR Foundation のドキュメントをご覧ください。
 - Unity の AR Foundation 向け ARCore Extensions に関する Google のドキュメントをご覧ください。
 
ボーナス課題
ここで作成したゲームを拡張したい場合は、次のアイデアをお試しください。
PackageManagerが新しいパッケージをスポーンしたときにTextMeshProを変更して、ゲームにスコアカウンタを追加します。- パフォーマンス オーバーレイを有効にして、ゲームの実行中にパフォーマンス情報を確認します。
 - 永続的なレイキャストを使用して、まずシーンに新しいオブジェクトを配置します。その領域で平面が検出されると、そのオブジェクトが更新され、その平面にスナップされます。