技術にっき

気になる技術について呟いてます

ARCoreの検出平面を非表示にする

ARCore の検出平面を非表示にしたい!

検出平面の表示 / 非表示

Google が開発した SDK である ARCore で
検出した面を可視化した「検出平面」を非表示にする方法を調べてみました。

今回は ARCore のサンプルシーンである HelloAR を題材に
Unityを用いたARアプリ開発における
この問題の解決方法の一つを紹介します。

Unity バージョン:Unity 2019.2.5f1


検出平面を非表示にする方法

あるイベントが発生したときに
検出平面を非表示にする方法は次の2つが考えられます。

  • イベント発生時に、検出平面の Prefab(設計書)を変更する
  • イベント発生時に、検出平面のインスタンスを非表示にする

今回は後者の方法を紹介します。

検出平面のインスタンスを非表示にする方法

この方法では、以下の2つの手順で検出平面を非表示にします。

1.シーン中に存在する検出平面のインスタンスを非表示にする
2.新たに生成される検出平面を非表示にする

以降で各手順について説明します。

1.シーン中に存在する検出平面のインスタンスを非表示にする

前段階で検出平面のPrefabに "Plane" という Tag を設定しておき
イベント発生時に Tag から検出平面のインスタンスを探して非表示にします。

検出平面の Prefab に "Plane" という Tag を設定する

まず、検出平面の管理を行っている(インスタンスを生成している)GameObject を
探します。
(HelloAR の場合は Plane Generator)


次に GameObject にアタッチされている Prefab を Inspector 上でダブルクリックします。
この Prefab が検出平面の設計書です。
(HelloAR の場合は DetectedPlaneVisualizer)

検出平面の Prefab の Tag から Add tag... を選択し


"Plane" を Tag に作成して


"Plane" Tag を Prefab に設定します。


これで前段階は完了です。

イベント発生時に検出平面のインスタンスを非表示にする

まず、検出平面を非表示にしたいイベントが書かれているスクリプトを開きます。
(HelloAR で、あるイベント="画面タッチ"と考えた場合は HelloARController.cs)

次に、スクリプトのクラスの中で下記のメソッドを宣言します。

// HelloARController.cs

public void VisualizePlanes(bool showPlanes)
{
  foreach (GameObject plane in GameObject.FindGameObjectsWithTag("Plane"))
  {
      Renderer r = plane.GetComponent<Renderer>();
      DetectedPlaneVisualizer t = plane.GetComponent<DetectedPlaneVisualizer>();
      r.enabled = showPlanes;
      t.enabled = showPlanes;
  }
}


スクリプト中のイベント発生時処理が書かれている部分に次の一文を追加することで
"Plane" Tag がついたシーン中のインスタンス(検出平面)を非表示にできます。
(HelloAR で、あるイベント="画面タッチ"と考えた場合は HelloARController.cs)
※非表示にした検出平面は見えなくなるだけで、追跡はし続けます。

// HelloARController.cs

VisualizePlanes(false);


以上により、
イベント発生時にシーン中に存在する検出平面のインスタンス
非表示にすることができました。

しかし、新たに検出した平面は表示されてしまいます。
この問題を解決するために、次の手順を実施します。

2.新たに生成される検出平面を非表示にする

イベント発生に関するフラグを作成して、あらたな検出平面のインスタンス生成時に
フラグを参照することで検出平面を非表示にします。

イベント発生に関するフラグを作成する

まず、検出平面を非表示にするときのイベントが書かれているスクリプトを開きます。
次に、スクリプトのクラスの中で下記の変数を宣言・初期化します。

// HelloARController.cs

public bool visualizePlanesFlag1 = true;


※getter(), setter() の利用をおすすめします。

次に、この変数をイベント発生と関連させます。
手順1で宣言したメソッドを次のように書き変えます。

// HelloARController.cs

public void VisualizePlanes(bool showPlanes)
{
  foreach (GameObject plane in GameObject.FindGameObjectsWithTag("Plane"))
  {
      Renderer r = plane.GetComponent<Renderer>();
      DetectedPlaneVisualizer t = plane.GetComponent<DetectedPlaneVisualizer>();
      r.enabled = showPlanes;
      t.enabled = showPlanes;
  }
  visualizePlanesFlag = showPlanes;
}


これによりイベント発生に関するフラグを作成することができました。

フラグを参照して新たに生成される検出平面を非表示にする

まず、検出平面の Prefab にアタッチされている
検出平面を可視化させるためのスクリプトを開きます。
(HelloAR の場合は DetectedPlaneVisualizer.cs)

次に、スクリプトのクラスの中で下記の変数を宣言・初期化します。

// DetectedPlaneVisualizer.cs

public bool visualizePlanesFlag2 = true;


また、スクリプト中の Awake() メソッドを次のように書き変えます。

// DetectedPlaneVisualizer.cs

public void Awake()
{
  m_Mesh = GetComponent<MeshFilter>().mesh;
  m_MeshRenderer = GetComponent<UnityEngine.MeshRenderer>();

  GameObject obj = GameObject.Find("HelloAR Controller");
  HelloAR.HelloARController script = obj.GetComponent<HelloAR.HelloARController>();
  visualizePlanesFlag2 = script.visualizePlanesFlag1;
}


最後に、Update() メソッドを次のように書き変えます。

// DetectedPlaneVisualizer.cs

public void Update()
        {
            if (m_DetectedPlane == null)
            {
                return;
            }
            else if (m_DetectedPlane.SubsumedBy != null)
            {
                Destroy(gameObject);
                return;
            }
            else if (m_DetectedPlane.TrackingState != TrackingState.Tracking)
            {
                 m_MeshRenderer.enabled = false;
                 return;
            }

            if (visualizePlanesFlag2 == false)
            {
                m_MeshRenderer.enabled = false;
            }
            else
            {
                m_MeshRenderer.enabled = true;
            }

            _UpdateMeshIfNeeded();
        }


以上により、
イベント発生以降で新たに生成される検出平面を非表示にすることができました。

まとめ

今回紹介した手順1と手順2の方法によって、イベント発生以降の検出平面を
非表示にすることができました。
これにより、外観を阻害することなく AR 体験を提供できます。
参考になれば幸いです。

参考:How to stop Plane Detection in ARCORE v1.2.0
  【Unity】他のスクリプトファイルのメソッド(関数)を実行する方法


※当ブログに掲載された内容によって生じた損害等の一切の責任を負いかねますので
 ご了承ください。
 当サイトで掲載している画像や動画の著作権・肖像権等は各権利所有者に
 帰属致します。