UnityでARKit3を動かすためにAR Foundationを使ってみる

## 前置き
最近何かとARKit3が話題ですね。ARKit3をUnityで使いたい場合はどうすればいいでしょうか？

ARKit2.0までは[Unity-ARKit-Plugin](https://bitbucket.org/Unity-Technologies/unity-arkit-plugin)を用いることでUnityでARKitを使うことができましたが、ARKit3についてUnity-ARKit-Pluginの公式ページには以下のように書かれています。

> This plugin will not be updated to support ARKit 3 features. Please use AR Foundation in order to access all ARKit features going forward.

Unity-ARKit-Pluginではなく、今後はAR Foundationにてサポートしていくようです。そのため来たるARKit3公式リリースに備え、AR Foundationを使ってみましょう。

**※ARKit3はiOS13でしか動作せず、iOS13はまだApple Developer Programの開発者にのみ公開されたベータ版で、NDAに基づき情報が公開できないため、公式リリースしたら別途まとめたいと思います。**

## AR Foundationとは？

「ARKit・ARCoreをUnityで用いるためのマルチプラットフォーム API」
という認識で良いと思います。今後も対応プラットフォームは増えるそうです。

[公式ページ](https://docs.unity3d.com/Packages/com.unity.xr.arfoundation@2.2/manual/index.html)には以下のように記述されています。

> AR 開発に伴う様々な難しい問題の解決に役立つマルチプラットフォーム API とユーティリティを開発しました。私たちはこれを AR Foundation と名付けました。

AR Foundationについて詳しくは以下のページが参考になるかと思います。(というかほぼ内容一緒です。。)
[【Unity】AR Foundation（ARKitとARCoreのマルチプラットフォームAR環境）の超入門](http://tsubakit1.hateblo.jp/entry/2018/11/21/211400)

## AR Foundationの導入方法
Package Managerを使って導入します。
ファイルメニューからWindow > Package Managerを開き、
- AR Foundation (2.2.0)
- ARKit XR Plugin (2.1.0)
をインストールします。

<img width="726" alt="Screen_Shot_2019-06-30_at_23_36_06.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/71629/b706f43f-1933-4b29-3274-a152c2df9eae.png">

ARKit XR PluginのChangelogを見てみると、2.2.0からARKit 3の機能が含まれてしまうため、iOS13でない場合、実機でエラーが出てしまいます。そのため、ARKit XR Pluginはバージョン2.1.0を使いました。
https://docs.unity3d.com/Packages/com.unity.xr.arkit@2.2/changelog/CHANGELOG.html

(Unityのバージョンは`2019.1.5f1`を使用しました。)


## ARに必要なコンポーネントの配置

新しくシーンを開きます。デフォルトで配置されているMain Cameraは削除しましょう。

続いて、ファイルメニューから
- GameObject > XR > AR SessionOrigin
- GameObject > XR > AR Session
を選択してシーンに追加します。

<img width="299" alt="Screen Shot 2019-06-30 at 21.00.35.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/71629/b28d47a8-068c-1bfa-91bc-d51466e20bd8.png">

ここで`ARSessionOrigin`はARCameraや検出した平面・point cloudなどのARのセットアップに必要なオブジェクトをまとめる親オブジェクトです。

`ARSession`はAR体験のライフサイクルを制御します。ARSessionは開始、停止、再開、終了が行えます。

## 検出した平面を表示する
検出した平面を表示してみます。

ヒエラルキーのAR Session OriginオブジェクトにARPlaneManager.csをアタッチします。
Detection Mode は`Everything`にしましょう。Horizontal,Verticalを同時に検出します。

続いて検出した平面を可視化するPlaneを作成します。
ファイルメニューから GameObject > XR > AR Default Planeを選択してシーンに追加後、プロジェクトウインドウにドラッグ&ドロップしPrefab化します。
作成した`AR Default Plane` Prefabを`AR Session Origin`オブジェクトの`ARPlaneManager.cs`コンポーネントの`Plane Prefab`にドラッグアンドドロップします。

<img width="445" alt="Screen Shot 2019-06-30 at 21.36.40.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/71629/b73c57ff-2ef1-d00f-a651-ebe392e04bb8.png">

## AR空間のタッチした位置にオブジェクトを配置
平面上のタッチした位置にCubeを置いてみましょう。
画面のタッチされた位置から検出した平面までRayを飛ばす必要があります。
Rayを飛ばすために`AR Session Origin`オブジェクトに`ARRaycastManager.cs`をアタッチします。

ここで、以下のスクリプトを作成します。

```CreateObject.cs
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR.ARFoundation;

[RequireComponent(typeof(ARRaycastManager))]
public class CreateObject : MonoBehaviour
{
    [SerializeField]
    GameObject objectPrefab;

    ARRaycastManager raycastManager;
    List<ARRaycastHit> hitResults = new List<ARRaycastHit>();

    void Awake()
    {
        raycastManager = GetComponent<ARRaycastManager>();
    }

    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            if (raycastManager.Raycast(Input.GetTouch(0).position, hitResults))
            {
                Instantiate(objectPrefab, hitResults[0].pose.position, Quaternion.identity);
            }
        }
    }
}
```

作成した `CreateObject.cs` を `AR Session Origin` オブジェクトにアタッチします。
CubeなどのPrefabを作成し、Object Prefabにドラッグ&ドロップでアタッチします。
 <img width="445" alt="Screen Shot 2019-06-30 at 21.54.37.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/71629/44161ece-b1af-d9c2-bb40-5e616a7b751a.png">

## 実機で確認
XCodeプロジェクトにビルドし、実機で確認してみます。

![ARFoundation Test](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/71629/5bcb5a66-8629-c178-fc43-46de3663d727.jpeg)

画像のように平面を検出し、タッチした位置にオブジェクトを配置できました。

## AR Foundationを触ってみた所感
導入がすごく楽です。今まではBitbucketからzipをダウンロードしてインポートの流れでしたが、Package Managerからぽちぽちでインストールできるので大変楽です。ARKitRemoteのようにUnity Editor上でARの動作のデバッグができないのが難点でしょうか。

## ARKit3を扱う場合
導入方法の項でも書きましたが、ARKit XR Pluginはバージョンを2.2.0にあげればARKit3の機能を扱うことができます。
そしてApple Developer Programに登録し、XCode11をダウンロード、実機のOSをiOS13にアップデートする必要があります。XCode11だけなら無料の開発者アカウントでもダウンロードできますが、iOS13にアップデートするには年間登録料99米ドルを支払ってメンバーシップを変更する必要があります。

以下の公式レポジトリにサンプル集があります。masterブランチにはARKit3のサンプルも含まれており、Apple Developer Programの開発者は実機にて動作させることができますので、そちらで実際にARKit3を体験することができます。
https://github.com/Unity-Technologies/arfoundation-samples

## 参考ページ
http://tsubakit1.hateblo.jp/entry/2018/11/21/211400
https://docs.unity3d.com/Packages/com.unity.xr.arfoundation@2.2/manual/index.html