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

前提条件
Lightship ARとLightship Meshingを有効にしたUnityプロジェクトが必要です。 詳細については、 ARDK 3.0 のインストール と How to Mesh: Adding Physics(メッシュの操作方法: 物理演算の追加) を参照してください。
また、Unity GameObject と AR Mesh Manager および Lightship Meshing Extension コンポネントが必要です。 詳しくは、 メッシュの作成のセクション1の手順に従ってください。
このチュートリアルを始める前に、この画像のようにシーンでメッシュが生成されていることを確認してください。 確認できたら、プレハブの シェーダー を変更してメッシュを不可視にし、このガイドに従ってナビゲーションの追加を開始します。

Navigation Mesh Managerの追加
::注意 重要です!
このガイドはレイヤーマスクのすべてが選択されていることを前提としています。 レイヤーマスクを変更したい場合は、エージェントのプレハブのレイヤーをLightshipNavMeshManager で設定されているものに設定してください! レイヤーの作成について詳しくは、 Unityのドキュメントをご覧ください。
:::
LightshipNavMeshManagerを追加する:
- 空の GameObjectを作成する。- Hierarchyで、シーンのルートを選択します。
- メインメニューから、 GameObject を選択し、次に Create Empty を選択します。
- NavMeshManager という名前を付けます。
 
- NavMeshManager オブジェクトに LightshipNavMeshManagerコンポーネントを追加します。- Inspector ウィンドウで、 Add Componentをクリックします。
- 検索窓に「LightshipNavMeshManager」と入力し、選択します。
- コンポーネントに Main Camera を追加します。 ここを起点に、マネージャーでメッシュ上で有効なパスをスキャンします。
 
- LightshipNavMesh を表示する場合は、 NavMeshManager に LightshipNavMeshRendererコンポーネントも追加します。 これにより、カメラが動くと LightshipNavMesh が画面上にレンダリングされます。- Inspector ウィンドウで、 Add Component を再度クリックします。
- 今回は、代わ りに "LightshipNavMeshRenderer "を検索して選択します。
- LightshipNavMeshManagerをコンポーネントに追加します。
- ナビゲーション・メッシュのレンダリングに使用するマテリアルを作成し、それをコンポーネントに追加します。
 
 
NavMesh サンプルプロジェクトの LightshipNavMeshManager プレハブを追加することもできます。 詳細については、 サンプルプロジェクト をご覧ください。
これで、エディターで「Play」ボタンを押すと、タイルのグリッドが生成されるようになりました。 次に、ナビゲーションメッシュ上を移動できるエージェントを追加します。

LightshipNavMeshManager の Scan Range の値を上げることで、カメラ周辺に広範囲のタイルのグリッドを作成できます。
LightshipNavMeshへのエージェントの追加
LightshipNavMesh をテストするには、その上を動き回る Agent をシーンに追加する必要があります。 ゲームボードのサンプルプロジェクト にはテスト用の Agent プレハブが含まれていますが、代わりに自分で作成することもできます。
Agent プレハブを作成します:
- Agent として動作するオブジェクトをシーンに追加するには、次の手順を行います。
- Hierarchyで、シーンのルートを選択します。
- 右クリックして Create Empty を選択し、 新しい空のオブジェクトに TestAgentと名前を付けます。
 
- 新しい Agent に LightshipNavMeshAgentコンポーネントを追加します。- Hierarchyで、 TestAgentを選択します。
- Inspector ウィンドウで、 Add Componentをクリックします。 「LightshipNavMeshAgent」を検索し、選択してコンポーネントを追加します。
 
- Hierarchyで、 
- LightshipNavMeshAgentPathRendererコンポーネントを追加して、 Agent がシーン内で通ることができるパスを表示します。- Inspector ウィンドウで、 Add Componentをクリックし、"LightshipNavMeshAgentPathRenderer" を検索して選択し、コンポーネントを追加します。
- LightshipNavMeshAgentと Material プロ パティを設定します。
 
- Agent を表すキューブを追加する手順は以下のとおりです。
- Hierarchy で TestAgentを右クリックし、 3D Object にカーソルを合わせます。 この例では、 Cube を選択して、基本キューブをテスト Agentとして追加します。
- インスペクタの変形ウィンドウで、立方体のスケールを(0.2, 0.2, 0.2)に設定して縮小します。
- キューブの底が (0, 0, 0) になるように、キューブの位置を (0, 0.1, 0) に変更します。
- Box Collider の横にあるボックスのチェックを外して無効にします。 これにより、キューブエージェントが生成されたメッシュと衝突するのを防ぐことができます。
 
- Hierarchy で 
 
- Agent を Assets ウィンドウにドラッグしてプレハブにし、シーンから削除します。
 
エージェントを制御するスクリプトを作成します。
Agentにコントロールスクリプトを追加するには:
- ユーザー入力を管理してエージェントを制御するためのスクリプト Asset を作成します。
- Assets ウィンドウの空いているスペースを右クリックし、 Create にカーソルを合わせ、 C#スクリプト を選択します。
- 新しいスクリプトに NavMeshHowToという名前をつけます。
 
- コードエディターでスクリプトを開きます。
- 以下の手順で、タップ入力を処理するコードを設定します。
- 「HandleTouch」というプライベートメソッドを作成します。
- エディターでは、「Input.MouseDown」を使用してマウスクリックを検出します。
- スマートフォンでは、「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
 {
 // タップで何かのアクションを行う
 }
 }
- 画面のタップポイントを3D座標に変換します。
- 
スクリプトの先頭にCameraフィールドを追加します。 [SerializeField]
 private Camera _camera;[SerializeField]を使用すると、プライベートプロパティをInspectorウィンドウに表示できるようになります。
 
- 
:::
- 
Unityの Camera.ScreenPointToRay関数を使用します。 「HandleTouch」メソッド内でカメラからのレイを作成します。#if UNITY_EDITOR
 Ray ray = _camera.ScreenPointToRay(Input.mousePosition);
 #else
 Ray ray = _camera.ScreenPointToRay(touch.position);
 #endif
- 
「Physics.Raycast」を使ってレイがメッシュに当たるかどうかをチェックし、結果のポイントを取得します。 {
 // タップで何かの処理を行う
 RaycastHit hit;
 if (Physics.Raycast(ray, out hit))
 {
 // 3Dポイントを使ってエージェントを誘導
 }
 }
- 
タップで取得した3Dポイントを使用してエージェントを誘導する - 先ほど作成したプレハブからエージェントをインスタンス化します。
- エージェントプレハブ向けに、クラスの上部に LightshipNavMeshAgentフィールドを追加します。[SerializeField]
 private LightshipNavMeshAgent _agentPrefab;
- エージェントのインスタンスとして使用するプライベートの LightshipNavMeshAgentフィールドをエージェントプレハブの下に追加します。private LightshipNavMeshAgent _agentInstance;
- エージェントインスタンスは、シーン内でエージェントプレハブから生成された特定のオブジェクトです。 このプレハブはインスタンスを作成するための設計図として使用されます。
- エージェントがまだ存在しない場合は、ヒットポイントで作成します。 存在する場合は、 NavMesh上での新しい目的地をヒットポイントに設定します。// タッチで何かします
 RaycastHit hit;
 if (Physics.Raycast(ray, out hit))
 {
 // エージェントを誘導するために3Dポイントを使用します
 if (_agentInstance == null )
 {
 _agentInstance = Instantiate(_agentPrefab);
 _agentInstance.transform.position = hit.point;
 }
 else
 {
 _agentInstance.SetDestination(hit.point);
 }.
 }
 
- 
スクリプトでタッチの有無がフレームごとにチェックされるように、「HandleTouch」メソッドをUpdateメソッドに追加します。 void Update()
 {
 HandleTouch();
 }
- 
スクリプトを NavMeshManager にアタッチします。 - Hierarchyで NavMeshManager GameObjectを選択し、 Inspector ウィンドウで「Add Component」をクリックします。
- NavMeshHowTo "を検索し、それを選択してコントローラスクリプトをプレハブに追加します。
- Camera と Agent Prefab のプロパティを設定してください。
   
- 
これで、キューブをスポーンさせて ナビゲーション・メッシュ 上の任意のタイルに向けることができるようになりました。  
- 
NavMesh ビジュアルをオプションにして見た目をきれいにしましょう。 NavMeshHowToスクリプトで次の手順を実行します。- LightshipNavMeshManagerにフィールドを追加して、レンダラーコンポーネントへの参照を取得します。- [SerializeField]
 private LightshipNavMeshManager _navmeshManager;
- NavMeshRenderer コンポーネントを取得して、そのステートを設定する「 SetVisualization」という新しいメソッドを作成します。
public void SetVisualisation(bool isVisualizationOn)
 {
 //navmeshのレンダリングをオフにする
 _navmeshManager.GetComponent<LightshipNavMeshRenderer>().enabled = isVisualizationOn;
 if (_agentInstance != null)
 {
 //エージェントのパスレンダリングをオフにする
 _agentInstance.GetComponent<LightshipNavMeshAgentPathRenderer>().enabled = isVisualizationOn;
 }
 }
- UIボタンやスクリプトから、このメソッドを呼び出します。
 

クリックして最終的な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);
                }
            }
        }
    }
}