「UnityのARFoundationでAR空間に豆腐を召喚する」をやって、ARFoundationをフレームワークとして使う上で困らないレベルに理解してみた

#はじめに
ARFoundationを利用したオリジナルARアプリを作成するにあたり、@shun-shun123さんのQiita記事にあった「UnityのARFoundationでAR空間に豆腐を召喚する」を練習でやってみた。
元記事URL：https://qiita.com/shun-shun123/items/1aa646049474d0e244be

今回は、上記記事を通じて「ARFoundationをフレームワークとして使う上で困らないレベルに理解してみた」内容を書いていこうと思う。（ほぼ公式サイトを和訳しただけ）
※ARFoundationで提供されるスクリプトのコード理解も後でやりたい
Unity公式サイト ARFoundationページ：https://docs.unity3d.com/Packages/com.unity.xr.arfoundation@3.0/manual/index.html#basic-setup

#環境
Unity 2019.3.0f6 
ARFoundation 3.0.1
AR Subsystems 3.0.0
ARKit XR Plugin 3.0.1
XR Legacy Input Helpers 1.3.8
Xcode 11.3.1
macOS Catalina 10.15.2
iOS 13.2.3

#基本設定
まずはじめにSceneに「AR Session」と「AR Session Origin」をGameObjectとして追加する。
![2020-02-12 13.08のイメージ.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577878/aba4e262-0bd6-e978-4ee8-26d76cd5dec1.jpeg)
![2020-02-12 13.07のイメージ.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577878/b4554d4f-4144-b128-045c-2f526a58cdc7.jpeg)
※画像はUnity公式サイトより

この２つのObjectはAR機能を実装する上で必須らしい。
それぞれが果たしている役割が公式サイトに書いてあったので読んでみた。

###AR Session
・一連のAR体験をコントロールする（セッション機能）
・ターゲットのプラットフォーム（実機等）でAR機能を利用可能/不能にする

###AR Session Origin
・検知したObjectの特徴（位置・向き・大きさ）を確定させる

AR体験においては、「現実世界で検知したものをデジタルなGameObjectとして認識」or「現実世界にデジタルなGameObjectを生成」のように、カメラ越しにリアルとデジタルが重畳表示される。
その際に、例えばカメラが移動してもセッション開始時の原点を覚えておくことで、現実世界で適切にGameObjectの位置・向き・大きさを表示することができる。
 
このAR Session Originが果たす役割上（現実世界で適切にGameObjectの位置・向き・大きさを表示）、「現実世界を認識するCamera Object」&「現実世界に生成させるGame Object」は、AR Session Originの子Objectでなければならない。

![2020-02-12 13.07のイメージ.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577878/b4554d4f-4144-b128-045c-2f526a58cdc7.jpeg)
※AR CameraがAR Session Originの子Objectになっている。
※今回「現実世界に生成させるGameObject」である豆腐は、豆腐PrefabのジェネレータスクリプトをAR Session Originのコンポーネントにしている。


####AR Camera
初期設定から自分で変更した点があったので、ついでにAR Cameraについても書いておく。
上述の通り、AR Session Originの子Objectに配置されるAR Cameraだが、下記３つのコンポーネントを有している。

① AR Camera Manager
・実機カメラのAuto Focusモードのオン/オフ
・現実世界の光量計算機能のオン/オフ（パフォーマンスに大きく影響するので基本はオフに設定）
![2020-02-12 14.36のイメージ.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577878/f9bfb89e-dab7-8796-ae3f-b1cd4ff31299.jpeg)
※画像はUnity公式サイトより
 
② AR Camera Background
・実機カメラの映像を背景として表示させる（自分で背景映像をカスタム可能だが、ARアプリなら基本的にはこのまま使う）
![2020-02-12 14.37のイメージ.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577878/bf704283-d915-22a7-97a0-72fc61235fb8.jpeg)
※画像はUnity公式サイトより

③Tracked Pose Driver
・実機カメラの位置と向きを認識する（実機から位置・向き情報を読み出す）
![2020-02-12 14.50のイメージ.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577878/3b6f10b6-3ba9-a0ae-af46-6f467469d7ca.jpeg)
※画像はUnity公式サイトより

公式サイトには、「AR Cameraには上記３つのコンポーネントがある」と書いてあったのだが、私がAR Session OriginをSceneに追加したときには、Tracked Pose Driverではなく、AR Pose Driverとなっていた。
![2020-02-12 14.56のイメージ.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577878/4504e1a0-b6d8-3a9a-cd19-07d22c932329.jpeg)

後々、不具合が発生してもめんどくさいので、公式サイトに則ることにし、AR Pose DriverをDelete、Tracked Pose DriverをAddしておいた。
※AR Pose DriverとTracked Pose Driverの違いは、後ほどコードを紐解きつつ理解したい。


#平面検知 & 検知した平面に豆腐召喚
豆腐を召喚させる方法として、元記事ではまず平面検知をしていた。
平面検知の実装方法としては、AR Plane Managerを、GameObjectのAR Session Originにコンポーネントとして追加するだけで完了。
（厳密には、AR Plane Managerを、ScriptのAR Session Originと同様のGameObjectに追加していればOK）

また「画面タップしてRay（光線）を飛ばし、その光線と検知した平面が衝突した点に豆腐を召喚」という機能を実装するため、AR Raycast ManagerをAR Session Originにコンポーネントとして追加。 
最後にPlace On Plane（これは自分で１から書くScript）もAR Session Originにコンポーネントとして追加。
※この辺の実装方法・コードは元記事を見ていただきたい。
※元記事URL:

ちなみにAR Session OriginのInspectorは最終的にこんな感じになった。
![2020-02-12 17.03のイメージ.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577878/a69bc1bf-51e5-fd41-fa25-383d6e4f0a07.jpeg)

これで実装完了なのだが、最後の最後に戸惑った部分があったので共有しておく。
実際に実機（iPhone11 Pro）で動かしてみたときに、検知した平面をタップしても、豆腐が召喚されないという現象が起きた。エラーは何も見当たらないのに。
原因は、召喚した豆腐がデカすぎてカメラが豆腐の内側に入ってしまったため、召喚されていないように見えていただけだった。
TofuPrefabのScaleをX・Y・Zすべて 1→0.1 に変更して解決。


####Trackable Manager
AR Plane Managerは、ARFoundationで提供されるTrackable Managersのひとつで、Trackable ManagersはScriptのAR Session Originと同様のGameObjectに追加される必要がある。
理由は、前述した通り、AR Session Originが果たす役割である（現実世界で適切にGameObjectの位置・向き・大きさを表示）。

![2020-02-12 17.20のイメージ.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577878/76c2309f-80c8-d796-58c8-536b2e9fc34a.jpeg)
※画像はUnity公式サイトより
※ちなみにTrackable Managersは上記表の種類がある。
今回、平面検知に使用したAR Plane Manager だけでなく、例えばAR Tracked Image Managerを使用すれば人体検知ができたりする。


Trackable Managersは、各々が検知可能な現実世界の物体が定められており（あるいは自ら定義することも可能っぽい）、その物体検知に基づき、GameObjectの生成・削除を常にupdateしている。


#最後に
ARFoundationをフレームワークとして使える状態になるために、この記事を書いてみたが、人に説明できるまで理解するのはやっぱり難しい、、（まだコードの紐解きはできていないし、、、泣）

用語の使い方がおかしかったり、公式サイトの英語をニュアンスで理解してしまっている部分もあるので、間違っている部分があればご指摘いただけると幸いです。

あと、これまで新しいフレームワークを勉強するときは日本語のサイト・記事でどうにかしようとしてばかりいたけど、ARFoundationに関しては公式サイトが一番体系的で分かりやすかった。
英語から逃げてたらダメだ、、！！

Unity公式サイト AR Foundationページ：https://docs.unity3d.com/Packages/com.unity.xr.arfoundation@3.0/manual/index.html

####初めて知った用語たち
offset
https://wa3.i-3-i.info/word11923.html
→位置を基準点からの距離で表すこと

session
https://it-trend.jp/words/session
→接続を確立してから切断するまでの一連の通信のこと。