本文へスキップ

ナビゲーション・メッシュを追加する

ナビゲーション・メッシュは、ポイント・アンド・クリックのタッチ入力を使って、キャラクター( エージェント)がARシーンをナビゲートすることを可能にする。

Dotyを使ったLightship NavMesh

前提条件

Lightship ARとLightship Meshingを有効にしたUnityプロジェクトが必要です。 詳細については、 ARDK 3.0 のインストールHow to Mesh: Adding Physics(メッシュの操作方法: 物理演算の追加) を参照してください。

また、Unity GameObjectAR Mesh Manager および Lightship Meshing Extension コンポネントが必要です。 詳しくは、 メッシュの作成のセクション1の手順に従ってください。

このチュートリアルを始める前に、この画像のようにシーンでメッシュが生成されていることを確認してください。 確認できたら、プレハブの シェーダー を変更してメッシュを不可視にし、このガイドに従ってナビゲーションの追加を開始します。

Lightship NavMesh Visual

LightshipNavMeshManagerを追加する:

  1. 空の GameObjectを作成する。
    1. Hierarchyで、シーンのルートを選択します。
    2. メインメニューから、 GameObject を選択し、次に Create Empty を選択します。
    3. NavMeshManager という名前を付けます。
  2. NavMeshManager オブジェクトに LightshipNavMeshManager コンポーネントを追加します。
    1. Inspector ウィンドウで、 Add Componentをクリックします。
    2. 検索窓に「LightshipNavMeshManager」と入力し、選択します。
    3. コンポーネントに Main Camera を追加します。 ここを起点に、マネージャーでメッシュ上で有効なパスをスキャンします。
  3. LightshipNavMesh を表示する場合は、 NavMeshManagerLightshipNavMeshRenderer コンポーネントも追加します。 これにより、カメラが動くと LightshipNavMesh が画面上にレンダリングされます。
    1. Inspector ウィンドウで、 Add Component を再度クリックします。
    2. 今回は、代わりに "LightshipNavMeshRenderer "を検索して選択します。
    3. LightshipNavMeshManager をコンポーネントに追加します。
    4. ナビゲーション・メッシュのレンダリングに使用するマテリアルを作成し、それをコンポーネントに追加します。
Lightship NavMesh Manager

NavMesh サンプルプロジェクトの LightshipNavMeshManager プレハブを追加することもできます。 詳細については、 サンプルプロジェクト をご覧ください。

これで、エディターで「Play」ボタンを押すと、タイルのグリッドが生成されるようになりました。 次に、ナビゲーションメッシュ上を移動できるエージェントを追加します。

Lightship NavMesh Visual
important

LightshipNavMeshManagerScan Range の値を上げることで、カメラ周辺に広範囲のタイルのグリッドを作成できます。

LightshipNavMeshへのエージェントの追加

LightshipNavMesh をテストするには、その上を動き回る Agent をシーンに追加する必要があります。 Gameboardサンプルプロジェクトには、テストに使えるAgentプレハブが含まれていますが、代わりに自分で作成することもできます。

Agent プレハブを作成します:

  1. Agent として動作するオブジェクトをシーンに追加するには、次の手順を行います。
    1. Hierarchyで、シーンのルートを選択します。
    2. 右クリックして Create Empty を選択し、 新しい空のオブジェクトに TestAgent と名前を付けます。
  2. LightshipNavMeshAgent コンポーネントを新しい Agentに追加する。
    1. Hierarchyで、 TestAgentを選択します。
    2. Inspector ウィンドウで、 Add Componentをクリックします。 「LightshipNavMeshAgent」を検索し、選択してコンポーネントを追加します。
  3. LightshipNavMeshAgentPathRenderer コンポーネントを追加して、 Agent がシーン内で通ることができるパスを表示します。
    1. Inspector ウィンドウで、 Add Componentをクリックし、"LightshipNavMeshAgentPathRenderer" を検索して選択し、コンポーネントを追加します。
    2. LightshipNavMeshAgentMaterial プロパティを設定します。
  4. Agent を表すキューブを追加する手順は以下のとおりです。
    1. HierarchyTestAgent を右クリックし、 3D Object にカーソルを合わせます。 この例では、 Cube を選択して、基本キューブをテスト Agentとして追加します。
    2. インスペクタ変形ウィンドウで、立方体のスケールを(0.2, 0.2, 0.2)に設定して縮小します。
    3. キューブの底が (0, 0, 0) になるように、キューブの位置を (0, 0.1, 0) に変更します。
    4. Box Collider の横にあるボックスのチェックを外して無効にします。 これにより、キューブエージェントが生成されたメッシュと衝突するのを防ぐことができます。
3Dキューブ・エディタのプロパティ
  1. AgentAssets ウィンドウにドラッグしてプレハブにし、シーンから削除します。
LightshipNavMesh Agent

エージェントを制御するスクリプトを作成する

Agentにコントロールスクリプトを追加するには:

  1. ユーザー入力を管理してエージェントを制御するためのスクリプト Asset を作成します。
    1. Assets ウィンドウの空いているスペースを右クリックし、 Create にカーソルを合わせ、 C#スクリプト を選択します。
    2. 新しいスクリプトに NavMeshHowTo という名前をつけます。
  2. コードエディターでスクリプトを開きます。
  3. 以下の手順で、タップ入力を処理するコードを設定します。
    1. 「HandleTouch」というプライベートメソッドを作成します。
    2. エディターでは、「Input.MouseDown」を使用してマウスクリックを検出します。
    3. スマートフォンでは、「Input.GetTouch」を使用してタップを検出します。
    private void HandleTouch()
    {
    // エディターではマウスクリック、スマートフォンではタップを使用
    #if UNITY_EDITOR
    if (Input.GetMouseButtonDown(0) || Input.GetMouseButtonDown(1) || Input.GetMouseButtonDown(2))
    #else
    //タップがない場合、またはタップでUI要素が選択されている場合
    if (Input.touchCount <= 0)
    return;
    var touch = Input.GetTouch(0);

    // タップが始まった瞬間のみカウント
    if (touch.phase == UnityEngine.TouchPhase.Began)
    #endif
    {
    // タップで何かのアクションを行う
    }
    }
  4. 画面のタップポイントを3D座標に変換します。
    1. スクリプトの先頭にCameraフィールドを追加します。

      [SerializeField]
      private Camera _camera;
      [SerializeField] を使用すると、プライベートプロパティをInspectorウィンドウに表示できるようになります。

:::

  1. Unityの Camera.ScreenPointToRay 関数を使用します。 「HandleTouch」メソッド内でカメラからのレイを作成します。

    #if UNITY_EDITOR
    Ray ray = _camera.ScreenPointToRay(Input.mousePosition);
    #else
    Ray ray = _camera.ScreenPointToRay(touch.position);
    #endif
  2. 「Physics.Raycast」を使ってレイがメッシュに当たるかどうかをチェックし、結果のポイントを取得します。

    {
    // タップで何かの処理を行う
    RaycastHit hit;
    if (Physics.Raycast(ray, out hit))
    {
    // 3Dポイントを使ってエージェントを誘導
    }
    }
  3. タップで取得した3Dポイントを使用してエージェントを誘導する

    1. 先ほど作成したプレハブからエージェントをインスタンス化します。
    2. エージェントプレハブ向けに、クラスの上部に LightshipNavMeshAgent フィールドを追加します。
      [SerializeField]
      private LightshipNavMeshAgent _agentPrefab;
    3. エージェントのインスタンスとして使用するプライベートの LightshipNavMeshAgent フィールドをエージェントプレハブの下に追加します。
      private LightshipNavMeshAgent _agentInstance;
    4. エージェントインスタンスは、シーン内でエージェントプレハブから生成された特定のオブジェクトです。 このプレハブはインスタンスを作成するための設計図として使用されます。
    5. エージェントがまだ存在しない場合は、ヒットポイントで作成します。 存在する場合は、 NavMesh 上での新しい目的地をヒットポイントに設定します。
      // タップで何かの処理を行う
      RaycastHit hit;
      if (Physics.Raycast(ray, out hit))
      {
      // 3Dポイントを使ってエージェントを誘導
      if (_creature == null )
      {
      _creature = Instantiate(_agentPrefab);
      _creature.transform.position = hit.point;
      }
      else
      {
      _agent.SetDestination(hit.point);
      }
      }
  4. スクリプトでタッチの有無がフレームごとにチェックされるように、「HandleTouch」メソッドをUpdateメソッドに追加します。

    void Update()
    {
    HandleTouch();
    }
  5. スクリプトを NavMeshManager にアタッチします。

    1. Hierarchyで NavMeshManager GameObjectを選択し、 Inspector ウィンドウで「Add Component」をクリックします。
    2. NavMeshHowTo "を検索し、それを選択してコントローラスクリプトをプレハブに追加します。
    3. CameraAgent Prefab のプロパティを設定してください。
    エディターでのLightship NavMesh Script
  6. これで、キューブをスポーンさせて ナビゲーション・メッシュ 上の任意のタイルに向けることができるようになりました。

    Agent Visualizerを使ったLightship NavMesh
  7. NavMesh ビジュアルをオプションにして見た目をきれいにしましょう。 NavMeshHowTo スクリプトで次の手順を実行します。

    1. LightshipNavMeshManager にフィールドを追加して、レンダラーコンポーネントへの参照を取得します。
      [SerializeField]
      private LightshipNavMeshManager _navmeshManager;
    2. NavMeshRenderer コンポーネントを取得して、そのステートを設定する「 SetVisualization」という新しいメソッドを作成します。
      public void SetVisualisation(bool isVisualizationOn)
      {
      //navmeshのレンダリングをオフにする
      _navmeshManager.GetComponent<LightshipNavMeshRenderer>().enabled = isVisualizationOn;

      if (_agentInstance != null)
      {
      //エージェントのパスレンダリングをオフにする
      _agentInstance.GetComponent<LightshipNavMeshAgentPathRenderer>().enabled = isVisualizationOn;
      }
      }
    3. UIボタンやスクリプトから、このメソッドを呼び出します。
エージェントを使ったLightship NavMesh
クリックして最終的なNavMeshHowToスクリプトを表示
using UnityEngine;
using Niantic.Lightship.AR.NavigationMesh;

/// 概要:
/// LightshipNavMeshSample
/// このサンプルは、LightshipNavMeshを使って、ユーザー主導のポイントとクリックナビゲーションを追加する方法を示します。
/// 画面を最初にタッチすると、エージェントのプレハブが配置されます。
/// 場所をタップすると、エージェントはその場所に移動します。
/// トグルボタンは、ナビゲーション・メッシュとパスの表示/非表示を切り替えます。
/// _agentPrefabにLightshipNavMeshAgentがあると仮定します。
/// 独自のエージェント・タイプを書いている場合は、それを入れ替えるか、継承します。
///
public class NavMeshHowTo : MonoBehaviour
{
[SerializeField]
private Camera _camera;

[SerializeField]
private LightshipNavMeshManager _navmeshManager;

[SerializeField]
private LightshipNavMeshAgent _agentPrefab;

private LightshipNavMeshAgent _agentInstance;

void Update()
{
HandleTouch();
}

public void SetVisualization(bool isVisualizationOn)
{
//navmeshのレンダリングを無効にする
_navmeshManager.GetComponent<LightshipNavMeshRenderer>().enabled = isVisualizationOn;

if (_agentInstance != null)
{
//アクティブなエージェントのパスレンダリングを無効にする
_agentInstance.GetComponent<LightshipNavMeshAgentPathRenderer>().enabled = isVisualizationOn;
}
}

private void HandleTouch()
{
//エディターではマウスクリック、スマートフォンではタップを使用
#if UNITY_EDITOR
if (Input.GetMouseButtonDown(0) || Input.GetMouseButtonDown(1) || Input.GetMouseButtonDown(2))
#else
var touch = Input.GetTouch(0);

//タップがない場合、またはタップでUI要素が選択されている場合
if (Input.touchCount <= 0)
return;
if (touch.phase == UnityEngine.TouchPhase.Began)
#endif
{
#if UNITY_EDITOR
Ray ray = _camera.ScreenPointToRay(Input.mousePosition);
#else
Ray ray = _camera.ScreenPointToRay(touch.position);
#endif
//スクリーン空間のタップした場所を3D空間に投影し、その位置をエージェントの目的地として設定
RaycastHit hit;
if (Physics.Raycast(ray, out hit))
{
if (_agentInstance == null )
{
_agentInstance = Instantiate(_agentPrefab);
_agentInstance.transform.position = hit.point;
}
else
{
_agentInstance.SetDestination(hit.point);
}
}
}
}
}