【Unity】ARFoundationを使ってオブジェクトを配置する

#はじめに
ARFoundationを使って、平面にARオブジェクトを配置するスタンダードなアプリを作ります。
オブジェクトのデバック用に使うことも多いので備忘録として残しておきます。

初学者にも分かり易いような**Unity×ARのHelloWorld**的記事に仕上げましたので、
手を動かしながら作ってみるといいかもです。

#環境
MacBook Pro : Catalina 10.15.5
Unity       : 2019.4.0f1
Xcode       : 11.5
iPhone 11Pro : 13.5.1

#ARプロジェクトの準備
###Packageのインストール
ファイルメニューのWindow > Package Managerから以下の2つをインポートします。
・AR Foundation(4.0.2)
・ARKit XR Plugin(4.0.1)
※「AR」で検索すると見つかりやすいです。
![スクリーンショット 2020-06-30 2.47.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293639/12d48b4a-f106-8fe7-7163-4b4d3d980290.png)

###AR Session Origin、 AR Sessionコンポーネントの配置
Hierarchyウインドウで右クリックし、以下の2つを追加します。
・XR -> AR Session
・XR -> AR Session Origin
※Packageが正しくインストールされていると「XR」の項目が追加されています。

###Main Cameraの削除
ARプロジェクトでは`AR Camera`を利用するので`Main Camera`は削除しておきます。
![スクリーンショット 2020-06-30 3.05.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293639/54d70854-c944-3ba0-39d6-824bf2240cc5.png)

##検出した平面の可視化
`AR Plane Manager.cs`というスクリプトを使用して、検出した平面を可視化させます。
不必要な場合はこのセクションを飛ばしてしまっても問題ありません。

###AR Default PlaneのPrefab化
もう一度Hierarchyウインドウで右クリックし、`AR Default Plane`を追加します。
・XR -> AR Default Plane

追加したら`AR Default Plane`をPrefab化してHierarchyからは削除します。
![スクリーンショット 2020-06-30 3.49.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293639/03f969ce-cd2f-82f1-678a-ce15a4e36443.png)

###AR Plane Managerをアタッチ
Hierarchyに配置済みの`AR Session Origin`に`AR Plane Manager.cs`をアタッチします。
Inspectorの`Plane Prefab`には、先ほどPrefab化した`AR Default Plane`をアタッチしましょう。
Detection Modeを変更することで、水平や垂直のみを検出するように変更が可能です。
![スクリーンショット 2020-06-30 4.19.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293639/c7bb3011-9797-915c-3f8b-000df914fcd5.png)

##タップ位置にARオブジェクトを配置する
`AR Placement Manager.cs`というスクリプトを作成し、タップした位置にrayを照射して、平面にぶつかった場合のみARオブジェクトを配置します。
今回はAsset Storeからインポートした、ロボットをARで出現させます。

###ロボットのインポート
下記URLからロボットをインポートします。
`Add to My Assets` → `Open in Unity`ボタンとクリックすると、「Unityを開きますか？」とポップアップが出現するので許可をします。
https://assetstore.unity.com/packages/3d/characters/robots/space-robot-kyle-4696

UnityのPackage Managerに飛ぶのでインポートをクリックします。
ProjectのAssets直下に`Robot Kyle`が追加されていれば大丈夫です。

###シーンにロボットを追加
Assets -> Robot Kyle -> Model -> Robot Kyleをシーンにドラッグアンドドロップします。
シーンに追加された`Robot Kyle`はInspectorからチェックを外し、非アクティブにしておきましょう。
また、Animationも利用しないためチェックを外しておきます。

※ARで表示させたいオブジェクトが大きすぎると、モデルの内側にカメラが埋まってしまい、モデルを確認できない場合があります。必要に応じてScaleを変更しておきましょう。
今回は(0.1, 0.1, 0.1)に変更します。
![スクリーンショット 2020-06-30 20.21.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293639/a237ed5b-a574-7dfe-a922-7183f1cc99b6.png)



###AR Placement Managerの作成
ARオブジェクトの配置を管理する`AR Placement Manager.cs`を作成します。
Project内で右クリック、Create -> C# Script で名前は`ARPlacementManager`にしてください。
スクリプトは以下のようにします。

```C#:ARPlacementManager.cs
using UnityEngine;
using System.Collections.Generic;
using UnityEngine.XR.ARFoundation;

//ゲームオブジェクトにアタッチすると、ARRaycastManager.csを必要な依存関係として自動的に加える。
[RequireComponent(typeof(ARRaycastManager))]
public class ARPlacementManager : MonoBehaviour
{
    [SerializeField]
    GameObject arObject;            //ARで表示するオブジェクト
    [SerializeField]
    private GameObject arCamera;    //ARで利用するカメラ
    ARRaycastManager raycastManager;
    List<ARRaycastHit> hitResults = new List<ARRaycastHit>();

    void Awake()
    {
        //RequireComponentで追加されたARRaycastManager.csを代入する。
        raycastManager = GetComponent<ARRaycastManager>();
    }

    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {

            //rayを照射して平面に当たっていた場合。
            if (raycastManager.Raycast(Input.GetTouch(0).position, hitResults))
            {

                //arObjectが非アクティブの場合、アクティブにする。
                if (arObject.activeSelf == false)
                {
                    arObject.SetActive(true);
                }

                //キャラクターがarカメラを向く。
                arObject.transform.position = hitResults[0].pose.position;
                Quaternion lookRotation = Quaternion.LookRotation(arCamera.transform.position - arObject.transform.position, Vector3.up);
                lookRotation.z = 0;
                lookRotation.x = 0;
                arObject.transform.rotation = Quaternion.Lerp(arObject.transform.rotation, lookRotation, 1);
            }
            else
            {
                return;
            }
        }
    }
}
```

作成したスクリプトは、Assets直下に`Scripts`フォルダ作って管理すると良さそうです。
![スクリーンショット 2020-06-30 21.21.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293639/2aa97982-2a94-8292-5f83-00f4b8a946c5.png)

###AR Placement Managerのアタッチ
`AR Session Origin`に、作成した`AR Plane Manager.cs`をアタッチします。
Inspectorの`Ar Object`、`Ar Camera`にはHierarchyに配置済みの`Robot kyle`と`AR Camera`をアタッチします。
![スクリーンショット 2020-06-30 21.37.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293639/5703abb3-17b2-daa0-f561-25bf99b065dd.png)

#Project Settings

###カメラの利用許可
カメラの利用を許可しないと、ビルド後にiPhoneのカメラが使えません。
Xcodeでも記述できますが、Unity側で設定してしまいましょう。

ファイルメニューのEdit -> Project Settingsを選択し、`Project Settings`を開きます。
Player -> Configuration -> Camera Usage Discriptionにテキストを記入することで、カメラの利用許可を求められるようになります。
![スクリーンショット 2020-06-30 22.00.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293639/faa8a596-02d6-e010-2bec-c6af26d5f628.png)

###XR Plug-in Management
ARFoundation4.0から`Plug-in Providers`の設定が必要になりました。
XR -> XR Plug-in Management -> Plug-in Providers -> ARKitにチェックを入れましょう。
<img width="590" alt="スクリーンショット 2020-07-05 19.54.48.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293639/22e9eed2-28ee-34c8-3cbd-362893319877.png">

#Build
ファイルメニューのEdit -> Build Settingsを選択し、`Add Open Scenes`をクリックして作成したシーンを`Scenes In Build`に追加します。
今回はiPhoneで動かしたいので`Platform`を`iOS`にして`Swith Platform`します。
※結構時間かかります。
![スクリーンショット 2020-06-30 22.12.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293639/8214aa7d-6a3e-9ad9-2025-7953490a72b1.png)
`Swith Platform`が終了したら`Build`しましょう。Unityでの作業は以上になります。

#動作確認
タップ時に正面を向いてくれるように配置されれば完成です。
お疲れ様でした！
![HelloAR_kyaegashi.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293639/875359c6-c2cc-b7fe-4e14-61245b52f1d9.gif)