UnityでARKitを使用する際、特に凝ったことをしないのであればHelpersにあるUnityARCameraManager.csによってセッションの管理をする形になるかと思います。
ただ、このコンポーネントを使用すると、たとえばシーン遷移によって再度トラッキングをし直したいというとき、前のセッションの情報が残ってしまいます。
というわけで、これの解決法を調べてみます。
まず、これで何が困るかと言うと、同じくHelpersにあるUnityARGeneratePlane.csを利用している際に、前のセッションで生成されたplaneが表示されないままになります。
そもそもどうやってplaneが生成されるかというと、UnityARGeneratePlaneが生成しているUnityARAnchorManagerがUnityARSessionNativeInterfaceのARAnchorAddedEventイベント発生時に同クラスのAddAnchorメソッドを実行することで生成されています。
UnityARSessionNativeInterface.ARAnchorAddedEvent += AddAnchor;
が、UnityARGeneratePlaneがシーン遷移などによってOnDestroyのタイミングでplaneのGameObjectを破棄し、再度UnityARCameraManagerを利用しているシーンに遷移してきたとき、セッションはAnchorを維持しているためARAnchorAddedEventは発火しないので、planeが再生成されない、ということになります。(たぶん)
というわけでどうしたらよいかというと、UnityARCameraManager.csの以下の部分に注目します。
m_session = UnityARSessionNativeInterface.GetARSessionNativeInterface();
(略)
ARKitWorldTrackingSessionConfiguration config = new ARKitWorldTrackingSessionConfiguration();
config.planeDetection = planeDetection;
config.alignment = startAlignment;
config.getPointCloudData = getPointCloud;
config.enableLightEstimation = enableLightEstimation;
m_session.RunWithConfig(config);
どうやらここでセッションのconfigを設定しているようです。
GetARSessionNativeInterfaceはARKitWorldTrackingSessionConfigurationの他、UnityARSessionRunOptionも指定することができます。
具体的には以下。
ARSession.RunOptions - ARSession | Apple Developer Documentation
どうやらデバイスの位置もアンカーもリセットすることができそうです。
というわけでUnityARCameraManager.csを以下のように書き換えてみます。
m_session = UnityARSessionNativeInterface.GetARSessionNativeInterface();
(略)
ARKitWorldTrackingSessionConfiguration config = new ARKitWorldTrackingSessionConfiguration ();
config.planeDetection = planeDetection;
config.alignment = startAlignment;
config.getPointCloudData = getPointCloud;
config.enableLightEstimation = enableLightEstimation;
var option = UnityARSessionRunOption.ARSessionRunOptionRemoveExistingAnchors | UnityARSessionRunOption.ARSessionRunOptionResetTracking;
m_session.RunWithConfigAndOptions (config, option);
これでSnapCameraARManagerがスタートする度にデバイスの位置もアンカーもリセットされ、planeも再生成されるようになりました。
めでたしめでたし。
2017.11.24追記
これだけだと作りによってはUnityARAnchorManagerによって登録されたUnityARSessionNativeInterface.ARAnchorAddedEventの購読が解除されなくて無駄にplaneが生成される可能性があるので、UnityARAnchorManagerのDestroyメソッドを以下のようにしてやるとより安心感があります。
public void Destroy () { UnityARSessionNativeInterface.ARAnchorAddedEvent -= AddAnchor; UnityARSessionNativeInterface.ARAnchorUpdatedEvent -= UpdateAnchor; UnityARSessionNativeInterface.ARAnchorRemovedEvent -= RemoveAnchor; foreach (ARPlaneAnchorGameObject arpag in GetCurrentPlaneAnchors()) { GameObject.Destroy (arpag.gameObject); } planeAnchorMap.Clear (); }