【Unity(C#)】ARFoundationで認識した平面をオンオフ、平面認識機能そのものをオンオフする方法

#はじめに
ARFoundationで平面を認識してあれこれできるのは知っていたので、
そのあれこれした**平面を手軽にオンオフできる機能は無いのか**調べました。
加えて、**平面認識機能そのものをオンオフする手法が無いか**も調べました。

調べる前はARPlaneManagerにRemovePlaneやStopRecognitionなどが
実装されていることをイメージしてましたが見当たりませんでした。

別の手段を取る必要があり、また思い出してたどり着くまでに時間がかかりそうなのでメモします。

#バージョン情報

| 諸々名前 | バージョン |
|:-:|:-:|
|  Unity | 2019.4.8f1(LTS)  |
|  ARFoundation |  4.1.1 |
|  ARCore XR Plugin | 4.1.1  |
| ARCore Kit Plugin  | 4.1.1  |
|  AR Subsystems | 4.1.1  |
|  XR Plugin Management | 3.2.16  |


#認識した平面をオンオフする

###Sessionをリセット

まず、Sessionそのものをリセットする手法です。

これは非常に簡単で、ARSessionのResetを呼び出すだけです。

```C#
 [SerializeField] private ARSession _session;
 
 //既存の平面をリセット
 _session.Reset();
```

ただし、この手法だと**平面認識そのものがやり直し**になってしまうので注意が必要です。

###生成したARPlaneをオフにする

ARPlaneManagerのtrackablesからARPlaneを取り出して全て非表示にします。
再利用したいときは逆の処理を行えばOKです。

```C#
[SerializeField] private ARPlaneManager _arPlaneManager;
 
foreach (ARPlane plane in _arPlaneManager.trackables)
{
    plane.gameObject.SetActive(false);
}
```
#平面認識機能そのものをオンオフ

ここまでの処理だけだと、生成されたPlaneを非表示にできても新たにPlaneが生成されます。
下記のように`requestedDetectionMode`を変更することで
平面認識機能のアクティブをモードから切り替えることができます。

```C#
[SerializeField] private ARPlaneManager _arPlaneManager;

//平面認識の機能をオフ
_arPlaneManager.requestedDetectionMode = PlaneDetectionMode.None;

//平面認識の機能をオン
_arPlaneManager.requestedDetectionMode = PlaneDetectionMode.Horizontal;
```

#タップした平面上にオブジェクトを正対して表示させる(おまけ)

タップした平面にオブジェクトを表示し、そのオブジェクトは常にユーザーの正面を向いている、、、
という内容を結構な頻度で実装するので備忘録として書き残しておきます。

```C#
[SerializeField] private GameObject _arObject;
[SerializeField] private ARRaycastManager _arRaycastManager;

private readonly List<ARRaycastHit> _hits = new List<ARRaycastHit>();

void Update()
{
	if (Input.touchCount > 0)
	{
		var touch = Input.GetTouch(0);
		    
		if (touch.phase == TouchPhase.Began)
		{
		    if (_arRaycastManager.Raycast(touch.position, _hits, TrackableType.PlaneWithinPolygon))
		    {
		        //RayとARPlaneが衝突したところのPose
		        var hitPose = _hits[0].pose; 
		        //オブジェクトの配置
		        _arObject.transform.position = hitPose.position;
		        var cameraPos = Camera.main.transform.position;
		        cameraPos.y = _arObject.transform.position.y;
		        _arObject.transform.LookAt(cameraPos);
		    }
		}
	}
}
```

回転より先に座標の移動済ませておかないと望んだ位置に出てこないのでこの手法の場合は順番注意です。


#最後に

>調べる前はARPlaneManagerにRemovePlaneやStopRecognitionなどが
実装されていることをイメージしてましたが見当たりませんでした。

冒頭で述べたこの部分ですが、フォーラムで直接言質取ったとかではないので
もしこんなのあるよってご存じの方いらっしゃいましたら教えてください。

#参考リンク
[Arfoundation How To Properly Remove Planes And Ref Points](https://forum.unity.com/threads/arfoundation-how-to-properly-remove-planes-and-ref-points.661762/)
[Trackable Managers](https://docs.unity3d.com/Packages/com.unity.xr.arfoundation@3.0/manual/trackable-managers.html?_gl=1*7a3z22*_ga*MjEwMDIxMTUyNy4xNTc5MjUxNTgw*_ga_1S78EFL1W5*MTYyNzkxNDA0Mi4yOC4xLjE2Mjc5MTQxMjYuNjA.&_ga=2.240121930.875681101.1627906622-2100211527.1579251580#enumerating-trackables)
[AR-Foundation Clean Plane Detection](https://forum.unity.com/threads/ar-foundation-clean-plane-detection.615031/)
[【Unity】ビルボードで常にカメラの方に向く木を作る](https://nn-hokuson.hatenablog.com/entry/2017/03/24/211211)
[【Unity】ARFoundation入門～機能解説から平面検知の実装まで～](https://rightcode.co.jp/blog/information-technology/unity-ar-foundation-introduction)