UnityでAR入門（AR Foundation編）


## 概要

UnityでARと言えば[Vuforia](https://unity3d.com/jp/partners/vuforia)ですが、Unity製の[AR Foundation](https://unity.com/ja/unity/features/arfoundation)もあります。VuforiaもAR Foundationも[ARKit](https://developer.apple.com/jp/augmented-reality/arkit/)/[ARCore](https://developers.google.com/ar/)を（全て対応しているわけではありませんが...）サポートしているものの**Vuforiaを用いてアプリをストアに申請する際に有料ライセンスが必要**で、ARコンテンツをUnityで開発する際は、今まではVuforiaだったもののおそらく今後、AR Foundationが要件に入ってくる案件がありそうですよね。

### VuforiaとAR Foundationの違い

なんといっても[Vuforia（PTC社）](https://vuforia.com/)は、Unity 4.xぐらいの頃からAR技術をUnityでサポートしてきた老舗なので、圧倒的にサポート類が違い、特に**SDKの機能が豊富**であることかなという所感です。

AR Foundationでは、開発者自身で対応しなければならないことがVuforiaでの対応よりも多く、Unityを触って日が浅い方は、圧倒的に挫折するため最初はVuforiaでのAR開発をオススメします。
どうしてもAR Foundationを触るのであれば、まずはVuforiaでAR技術に触れつつAPI・SDKについて理解し、VuforiaがなぜAR Foundationよりも**SDKの機能が豊富**なのかを把握すると良いでしょう。

さらにAR Foundationが、サポートしているデバイスよりもVuforiaの方が**圧倒的に多くのデバイスをサポートしている**ため、作ることだけでなく、作った後のこともセットに考えましょう。

### 前提

本記事では、ARについてやUnityの基本的な（入門関連の書籍に載ってあるような）内容は、割愛して解説していきます。
そのため、次の項目を考慮してませんのでご注意ください。

* ARの概要について
    * Vuforia, AR Foundation, ARKit, ARCore, ...etc
* Unityの基本的な詳細について
    * 基礎知識やアプリビルドなど

　
ARについて知りたい方は、「Unity AR 入門」などでググれば次のような記事が見つかるのでこちらなどでキャッチアップされてください。

* [【初心者向け】UnityでARアプリ開発できるまでの学習・勉強方法を紹介する](https://gurutaka-log.com/unity-ar-study)
* [【AR開発環境】Vuforia/ARfoundation/WebAR【2019/11追記】](http://bibinbaleo.hatenablog.com/entry/2017/07/09/200436)


　
また、現在2020年3月上旬時点でまとめているため、詳細が一部古くなります。

特にAR Foundation/ARKit/ARCoreは、2,3ヶ月に数回アップデートが行われているため、本記事をそのまま鵜呑みにされず、**あくまでも参考程度**にお願いします。


## 環境

* MacBookPro Mojave 10.14
* Unity 2019.2.9f1
    * AR Foundation 2.0.2
    * ARCore XR Plugin 2.0.2
    * ARKit XR Plugin 2.0.1
* Test Device
    * Galaxy note8 Android 9.0


## ゴール

今回は、**AR Foundationを用いてUnityChanをARで表示させる**ことです。
おそらく「UnityChan AR」などでググるとほとんどVuforiaでのAR対応が多く、AR Foundationでキャラクターを表示させる記事は少ないと思います（2020年3月上旬時点）。

![imageLicenseLogo.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82601/0434f53a-6521-0ce9-e1ef-934f7944b48d.png)

この作品はユニティちゃんライセンス条項の元に提供されています

## 準備

次の作業を行うこと

* [UnityChan公式](https://unity-chan.com/)の[ユニティちゃん 3Dモデルデータ](https://unity-chan.com/download/releaseNote.php?id=UnityChan)のリンク先にある`.unitypackage`をダウンロード
* 新規Unityプロジェクトを作成した後にPackage Managerから「AR Foundation」「ARCore XR Plugin」「ARKit XR Plugin」をインストールしておく
* UnityChanの`.unitypackage`データを開いて作成したプロジェクトにインポートする

　
今回扱うUnityChanのデータは、「Locomotion」以外のどれか好きなサンプルシーンを丸っとフル活用します。
初めて触る方は、事前にUnityChanを確認される際に間違ってわからずに何か変更して保存しないように注意しておきましょう。


## AR Foundation入門

最初から全部作ることは効率が悪いため、まずAR Foundationに慣れることが必要です。

去年のAdvent Calendarで @shun-shun123さん が[UnityのARFoundationでAR空間に豆腐を召喚する](https://qiita.com/shun-shun123/items/1aa646049474d0e244be)という記事を書かれており、ここで解説されている内容＝AR Foundation入門という感じなのでやってみましょー！

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">TechTrain Advent Calendar 4日目は書いていただきました！<br>ありがとうございます！<br><br>UnityのARFoundationでAR空間に豆腐を召喚する <a href="https://t.co/Fx3pyyeH5l">https://t.co/Fx3pyyeH5l</a> <a href="https://twitter.com/hashtag/Qiita?src=hash&amp;ref_src=twsrc%5Etfw">#Qiita</a></p>&mdash; スー/TechTrain/TechBowl☁Tokyo (@gurusu_program) <a href="https://twitter.com/gurusu_program/status/1202046517864890368?ref_src=twsrc%5Etfw">December 4, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

### ハマりポイント

上記の記事でAR Foundation入門した際にハマったポイントを紹介します。
~~今回はAndroidだけで検証したため、別の機会にiOSも試して情報を載せられたら追加しますmm~~

#### 追加: iOSビルド

下記リンク先を参考にされてくださいー

[Unityで認識した平面をポータル化して異世界を覗く【ARFoundation編】 - @ippo](https://qiita.com/ippo/items/d9c046bb365e2666ffdc)

#### 1. ARCoreがサポートしているGalaxy note8が`unsupported devices`となる

[同じ問題について書かれてあったフォーラムの記事](https://forum.unity.com/threads/unity-ar-foundations-unsupported-samsung-galaxy-note-8.550483/)を見つけ、単純にARCore XR Pluginをインストールしていないことが原因でした笑汗

AR FoundationでiOS/AndroidをターゲットにARアプリを開発される際は、必ずAR FoundationだけではなくARKit XR PluginとARCore XR Pluginも必要です（片方であれば上記記事の解説通りです）。

<img width="600" alt="スクリーンショット 2020-03-01 1.40.46.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82601/17a81390-a660-5bf0-871d-5ff8b7d2d162.png">


#### 2. 1の対応で再度アプリビルドするとビルドエラー

次のエラー内容でエラー内容をそのままググると[Introducing ARCore: An Android AR SDK for Unity](https://forum.unity.com/threads/introducing-arcore-an-android-ar-sdk-for-unity.490929/)というフォーラムの記事を見つけ、ここで解説されている設定をそのまま対応するとエラーが解消されましたー🙆‍♂️

ちなみにXR Settingsのところは特に触らなくてよく、逆に`ARCore Supported`にチェックをつけてしまうとまた別のエラーになります。
詳細まで追ってないので今回はスルーして別で調査しようと思いますー

<img width="800" alt="スクリーンショット 2020-02-29 22.29.42.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82601/f0b1b0a1-be34-62e6-703d-ab51ce607ece.png"><img width="400" alt="スクリーンショット 2020-02-29 22.41.24.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82601/fd2e89a2-85e0-35f8-138e-87cf28c11849.png"><img width="400" alt="スクリーンショット 2020-02-29 22.45.17.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82601/e1a0fdaa-c9b9-2aa8-11c9-d39755d04421.png">



## UnityChan for AR

① 上記で作ったシーンをコピー
② サンプルシーンにいるUnityChan（今回使用するUnityChanは『**unitychan_dynamic**』になります）をコピーして1のシーンにペースト
③ 持ってきたUnityChanを`unpack Prefab`して新しくプレハブ化

　<img width="800" alt="スクリーンショット 2020-03-02 13.21.33.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82601/7f77cdf7-fa75-f805-3f87-761862d21e64.png">
　<img width="800" alt="スクリーンショット 2020-03-02 13.22.20.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82601/4a6a544b-c04f-8a5d-c17c-fabf9b365d8a.png">

④ `AR Session Origin`にAddComponentしている`PlaceOnPlane`に付けているCubeを3で作ったUnityChanのプレハブに変更する（分かりやすいように変数名も変更）

　<img width="280" alt="スクリーンショット 2020-03-02 13.27.54.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82601/ae141966-b9e7-7d8f-92c6-a9451a00185a.png">

⑤ スクリプトの調整

```csharp
// unitychan_dynamicを使用した場合
// IdleChanger.cs

// void OnGUI()
// {
//     GUI.Box(new Rect(Screen.width - 110, 10, 100, 90), "Change Motion");
//     if (GUI.Button(new Rect(Screen.width - 100, 40, 80, 20), "Next"))
//         anim.SetBool("Next", true);
//     if (GUI.Button(new Rect(Screen.width - 100, 70, 80, 20), "Back"))
//         anim.SetBool("Back", true);
// }

public void NextAnim()
{
    anim.SetBool("Next", true);
}

public void BackAnim()
{
    anim.SetBool("Back", true);
}
```

⑥ uGUIでButtonを用意して`NextAnim`メソッドと`BackAnim`メソッドを登録

```csharp
using UnityEngine;
using UnityEngine.UI;

public class UiManager : MonoBehaviour
{
    [SerializeField] private Button nextAnimBtn;
    [SerializeField] private Button backAnimBtn;

    public void Show(GameObject unitychan)
    {
        if (!nextAnimBtn.gameObject.activeSelf && !backAnimBtn.gameObject.activeSelf)
        {
            var script = unitychan.GetComponent<UnityChan.IdleChanger>();
            nextAnimBtn.onClick.AddListener(script.NextAnim);
            nextAnimBtn.gameObject.SetActive(true);
            backAnimBtn.onClick.AddListener(script.BackAnim);
            backAnimBtn.gameObject.SetActive(true);
        }
    }
}
```

⑦ `PlaceOnPlane.cs`にスクリプトを追加

```csharp
// フィールド
[SerializeField] UiManager uiManager;

// Updateメソッド 36行目あたり
// Instantiateの後にスクリプトを追加
spawnedObject = Instantiate(unitychan, hitPose.position, unitychan.transform.rotation);
uiManager.Show(spawnedObject);
```

⑧ `Inspector`の対応と用意したButtonはDisebleに設定

<img width="400" alt="スクリーンショット 2020-03-02 13.38.12.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82601/4067e117-96e2-5020-0978-e60f28ae8e19.png"> <img width="400" alt="スクリーンショット 2020-06-09 21.16.36.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82601/60a33999-d47d-66b3-b0e2-3a2283550320.png">


### ビルド結果

　<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82601/d66aa621-fae0-6116-9286-b5a96a0a9bc6.jpeg">


## まとめ

これでAR FoundationでARアプリを作る入りが分かったんじゃないかなと思います。

ARは最初からGameObjectを配置しないため、Instantiateで生成する形になるのでARで表示させたいキャラクターなどにAddComponentしているコンポーネントにアクセスしたい時や今回のようなUI操作の場合、Instantiate後にあれこれ制御する手間がかかるなぁという所感でした。