はじめに

※Unityでの開発を前提として紹介します。

ARKit のポジショントラッキングという機能に着目し、 VR 空間で自分が動けるのではないかと考え、 AR と VR の切り替えを試してみました。

今回、単眼のみなので言葉の定義として以下のように捉えています。

  • AR : 現実世界が写っている画面
  • VR : 現実世界が写っておらず、CGのみが写っている画面 ※複眼ではないです。

開発環境のおさらい

たくさんのサイトで紹介していると思いますが、おさらいしておきます。

  • iPhone6s 〜
  • iOS11〜
  • Xcode9〜
  • Unity5.6.1.p1〜
    • Unityを使用する場合、iPhone 8 Plus では 2017.2.0f3が必要です。(画面がバグります。)
    • ネイティブ・UnrealEngine でも可
  • Unity ARKit Plugin
    • AssetStoreに公開しているものを使用。

Build 時の注意

  • ARKit は A9/A10チップのみ対応

詳細はこちらの記事から確認してください。

ちなみに、 iPhone 6以下の端末でも Build が通ってしまい、あたかも成功しているように見えるので注意が必要です。

  • UnityARkitRemote を利用する時は、Develop Build を忘れずに!!

詳細はこちらの記事から確認してください。

Develop Build でないと、 Profiler に繋ぐことが出来ません。 2017.1 からは Console から Connected Player を 選択出来るようになります。

ポジショントラッキングの使用方法

まずは、適当な GameObject を作成し、後述するポジショントラッキングのスクリプトを適用します。

次に、 vrCamera に任意のカメラを紐付けしてください。今回は MainCamera を付けます。
この時、今回は使用しないUnityARCameraManagerでやっているようなことをしてます。

CardBoard を利用する場合は、以下の2点を行うようにしましょう。

  • vrCamera に MainCamera の親オブジェクトを付ける
  • 回転情報を渡さないようにする

以下が、ポジショントラッキングのスクリプトになります。

    public class ARKitPositionTracker : MonoBehaviour {

      public Transform vrCamera;  //対象のカメラ

      private UnityARSessionNativeInterface m_session;  //ARKit との橋渡し。

      void Start()
      {
        Application.targetFrameRate = 60;

        m_session = UnityARSessionNativeInterface.GetARSessionNativeInterface();

        //ARkit を利用する為の初期設定
        ARKitWorldTrackingSessionConfiguration config = new ARKitWorldTrackingSessionConfiguration();
        config.planeDetection = UnityARPlaneDetection.Horizontal;
        config.alignment = UnityARAlignment.UnityARAlignmentGravity;
        config.getPointCloudData = true;
        config.enableLightEstimation = true;
        m_session.RunWithConfig(config);
      }

      void Update(){
          if (vrCamera != null)
          {
            Matrix4x4 matrix = m_session.GetCameraPose();

            //ARKit の回転情報をカメラに渡す。
            vrCamera.transform.localRotation = UnityARMatrixOps.GetRotation (matrix);

            //ARKit の座標情報をカメラに渡す。
            vrCamera.transform.localPosition = UnityARMatrixOps.GetPosition(matrix);
          }
      }
    }

VR ・ AR の切り替え

まずは、後述する切り替えスクリプトをUnityARVideoを適用している MainCamera につけてください。 この UnityARVideo が現実世界を写しています。
後は、 ChangeXR()を任意のタイミングで呼べば、 AR と VR の切り替えを行うことができます。

以下が切り替えスクリプトになります。

    public class SwitchXR : MonoBehaviour {

        public GameObject vrRoom; //VR の時に表示させたい GameObject

        public bool vrMode = false;

        private Camera m_mainCamera; //MainCamera

        private Material m_savedClearMaterial = null; //ARVideo のマテリアルを保存用

        void Start(){
            m_mainCamera = Camera.main;
        }

        //AR と VR の切り替え
        public void ChangeXR(){
            vrMode = !vrMode;
            if(vrMode)  changeToVR();
            else        changeToAR();
        }

        //VR への切り替え
        private void changeToVR(){
            m_mainCamera.clearFlags = CameraClearFlags.Skybox;
            vrRoom.SetActive(true);

            //AR Camera の破棄
            UnityARVideo arVideo = GetComponent<UnityARVideo>();
            m_savedClearMaterial = arVideo.m_ClearMaterial;
            Destroy(arVideo);
        }

        //AR への切り替え
        private void changeToAR(){
            m_mainCamera.clearFlags = CameraClearFlags.Depth;
            vrRoom.SetActive(false);

            //AR Camera の初期化
            UnityARVideo arVideo = this.gameObject.AddComponent<UnityARVideo>();
            arVideo.m_ClearMaterial = m_savedClearMaterial;
        }
    }

最終的に Inspector 上ではこのようになります

Setting

まとめ

ARKitDemo

gif では分かりづらいかもしれませんが、左下のボタンで AR と VR の切り替えが可能になっていて、ギャップロロゴを中心に自分が動くようにしています。

これを利用することで、面倒な設定をしなくても VR 内で自分が動くということが出来ます。このことに最初はすごい感動を覚えました。 この方法を応用することで色々なことが出来そうですね!

是非試してみてください。