【Unity】NavMeshSurfaceとは?AI Navigationで移動する範囲を決める

NavMeshSurfaceとは? Unity

こんにちは、ともくんのゲーム作り部屋にようこそ!

このページでは、

「NavMeshSurfaceってなに?」

「NavMeshSurfaceでどんなことができるの?」

というお悩みの方に向けた内容となっています。

Unityでは、AI Navigationというシステムを使うことで、特定の範囲を自動で移動するオブジェクトを作成することができます。

この自動で移動させる範囲を指定するのが、NavMeshSurfaceというコンポーネントです。

NavMeshSurfaceを使って、事前にベイク処理を行いNavMeshデータを作成しておくことで、そのデータを元にオブジェクトが自動で移動するようになります。

そこで、このページでは、UnityのNavMeshSurfaceというコンポーネントについて、どういうものなのか、また使い方や設定方法までをまとめていきます。

この記事を書いた人

ゲーム作りを学び始めた一児のパパです。
このブログは、子供から「ゲームを作ってみたい!」と言われ、非プログラマーでゲーム作りをしたことない僕が、ゲーム作りの本を読んで独学でゲーム開発を学んでいるブログです。
同じように初めてゲーム作りをしている方と一緒に学んでいけるようなブログに出来たらいいなと思っています。
また、「このコードはおかしい」とか「もっと良い書き方があるよ!」などあれば、どんどん指摘して頂けると助かります。

NavMeshSurfaceとは?

まずは、NavMeshSurfaceがどういうコンポーネントなのか紹介していきます。

NavMeshAgentが移動できる範囲を指定するもの

NavMeshSurfaceとは、前述の通り、AI Navigationのシステムにおいて、オブジェクトを自動で移動させる範囲を指定することができるコンポーネントです。

もう少し詳しく説明すると、AI Navigationでは、NavMeshSurfaceコンポーネントを使って、地形の面となるNavMeshと呼ばれるデータを作ります。

このNavMeshデータを作る際は、地形のオブジェクトのMesh RendererのデータもしくはColliderの形状を元にして作成していきます。

そして、NavMeshAgentコンポーネントを付けたオブジェクトは、このNavMeshデータの上だけを移動するようになり、さらに目的地などを指定することで、自動で最短の経路を探索して移動するようになります。

このように、AI Navigationにおいて、NavMeshSurfaceを使ってNavMeshデータを作成することで、NavMeshAgentが自動で移動できる範囲を指定することができます。

事前にベイク処理を行う必要がある

NavMeshSurfaceでNavMeshデータを作成する際は、事前にベイクと呼ばれる処理を行う必要があります。

このベイクというのは、NavMeshSurfaceで指定した地形をゲーム実行前に保存しておく処理のことで、ベイクを行っておくことで、NavMeshAgentが事前に経路を計算して移動することができるようになります。

ただし、ベイクは事前に行われる処理になるため、オブジェクトをゲームの途中で移動させたりしてしまうと、NavMeshデータと表示されているオブジェクトの位置がずれることになってしまいます。

そのため、NavMeshSurfaceを付けたオブジェクトは、基本的に途中で移動や変更を行うことができなくなります。

なお、NavMeshAgentの移動経路を途中で変更させたり、通路を塞ぐような障害物を表示させたいという場合は、NavMeshObstacleコンポーネントを使うことで、ゲーム実行中でも処理を変更させることができます。

NavMeshSurfaceの基本的な使い方

ここからは、NavMeshSurfaceの基本的な使い方について紹介していきます。

移動範囲となる親オブジェクトにNavMeshSurfaceを紐づける

まず、NavMeshAgentの移動範囲にしたいオブジェクトの親に、NavMeshSurfaceコンポーネントを紐づけていきます。

ここでは、以下のように複数のオブジェクトを配置して、これらの上をNavMeshAgentが移動するという処理を作ってみます。

ヒエラルキーウィンドウの+ボタンから「AI」の中にある「NavMesh Surface」を選択します。

すると、NavMesh Surfaceコンポーネントが紐づいた空オブジェクトが作成されるので、このオブジェクトを親として、移動させたい範囲のオブジェクトをその階層内に入れてあげます。

ベイク処理を行う

次に、NavMeshデータを作成するために、ベイク処理を行っていきます。

ベイク処理は、インスペクターウィンドウのNavMesh Surfaceにある「Nav Mesh Data」という項目で行います。

この中の「Bake」というボタンをクリックすることで、ベイク処理を行いデータが作成されます。

NavMeshのデータが作成されると、以下のようにシーンビュー上で指定された範囲が、デフォルトでは水色で表示されるようになります。

NavMeshAgentを配置して移動処理を作る

あとは、先ほどのNavMeshデータの範囲上に、NavMeshAgentを付けたオブジェクトを配置して、移動処理を作っていきます。

ここでは、以下のようにカプセル型の赤いオブジェクトを配置しておきます。

このオブジェクトを選択して、インスペクターウィンドウで「AddComponent」から「Navigation」の中にある「NavMeshAgent」を選択します。

そして、オブジェクトに以下のスクリプトをアタッチしておきます。

using UnityEngine;
using UnityEngine.AI;

public class AgentController : MonoBehaviour
{
    NavMeshAgent agent;

    void Start()
    {
        agent = GetComponent<NavMeshAgent>();
    }

    void Update()
    {
        // マウスをクリックした場合
        if (Input.GetMouseButtonDown(0))
        {
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);    // カメラからマウスカーソルの位置に向かうRay
            RaycastHit hit;
            if (Physics.Raycast(ray, out hit))  // Rayを飛ばしてオブジェクトとの衝突判定
            {
                agent.SetDestination(hit.point);    // マウスカーソルの位置に向かって自動で移動させる処理
            }
        }
    }
}

マウスでクリックした場所にNavMeshAgentが移動するようにしたいので、20行目でRaycastメソッドを使ってマウスのカーソル位置からのRayを飛ばしています。

また、22行目でSetDestinationメソッドで、オブジェクトとの衝突位置にNavMeshAgentが自動で移動するように処理を記述しています。

これでゲームを実行してみると、

マウスでクリックした位置に向かって、NavMeshAgentが自動で移動するようになりました。

NavMeshSurfaceの設定項目

ここからは、さらにNavMeshAgentの移動を制御できるように、NavMeshSurfaceの設定について紹介していきます。

Agent Type:どのNavMeshAgentのタイプが使うか

Agent Typeは、そのNavMeshSurfaceをどのNavMeshAgentのタイプが使用するかを決める項目で、NavMeshAgentの幅や高さなどを指定することができます。

そして、ここで指定したAgent TypeのNavMeshAgentだけが、その道を通れるようになります。

また、指定したAgent Typeに応じて、NavMeshデータも変わっていくことになります。

デフォルトでは「Humanoid」が設定されていますが、「OpenAgentSettings…」を選択することで、Agent Typeの設定の変更や新規作成を行うことができます。

Agent Types:Agent Typeの作成・編集・削除

Agent Typesは、どのAgent Typeを編集するかどうか、また新たに作成したり削除したりすることができる項目です。

+ボタンを押すと新たに作成されて、-ボタンを押すと選択されているAgent Typeが削除されます。

Name:Agent Typeの名前

Nameは、Agent Typeの名前を決める項目です。

Radius:Agent Typeの幅を指定する

Radiusは、Agent Typeの幅の半径を指定する項目で、デフォルトでは0.5となっています。

そして、NavMeshデータを作成する際には、オブジェクトの元となるMeshデータやColliderの形状よりも、Radiusで指定した半径分縮めたデータが作成されることになります。

例えば、表面の大きさが2×5のオブジェクトで、Radiusを「0.5」としてNavMeshデータを作ると、以下のように縮まったNavMeshデータが作成されます。

このRadiusを最小の「0.05」に変更してNavMeshデータを作ると、オブジェクトの表面とほぼ同じ形状でNavMeshが作成されて、オブジェクトの端までNavMeshAgentが近づけることになります。

Height:Agent Typeの高さを指定する

Heightは、Agent Typeの高さを指定する項目で、デフォルトでは2となっています。

NavMeshデータを作成する際に、このHeightで指定した高さよりも離れているオブジェクト同士では、それぞれの同じ場所で異なる高さのNavMeshが生成されます。

Step Height:Agent Typeが移動できる段差

Step Heightは、Agent Typeが移動できる段差の高さを指定する項目で、デフォルトは0.75となっています。

NavMeshデータを作成する際には、このStep Heightで指定した段差内であればNavMeshが生成されてNavMeshAgentが移動できますが、Step Heightよりも大きい段差になるとNavMeshが生成されず移動できなくなります。

Max Slope:Agent Typeが移動できる坂道の斜度

Max Slopeは、Agent Typeが移動できる坂道の斜度を指定する項目で、デフォルトでは45度となっています。

NavMeshデータを作成する際には、このMax Slopeの値よりも小さい斜度の坂道にはNavMeshが生成されて、それよりも大きい斜度の坂道はNavMeshが生成されないようになります。

Drop Height:オフメッシュリンク生成の最大の高さ

Drop Heightは、オフメッシュリンクを自動生成する際のオブジェクトが離れている最大の高さを指定している項目です。

そもそもオフメッシュリンクとは、オブジェクトが離れている部分を繋ぐための仕組みで、オフメッシュリンクが作成されていると、その間をNavMeshAgentが移動できるようになります。

このオフメッシュリンクは、手動だけでなく自動で生成することができ、その自動生成の際に離れている最大の高さを指定することができます。

Jump Distance:オフメッシュリンク生成の最大の長さ

Jump Distanceは、オフメッシュリンクを自動生成する際のオブジェクトが離れている最大の長さを指定している項目です。

先ほどのDrop Heightがオフメッシュリンクを生成する高さだったのに対して、Jump Distanceはオフメッシュリンクを生成する長さということになります。

Default Area:NavMeshデータを定義するエリア

Default Areaは、NavMeshのデータを作る際に定義するエリアを指定する項目です。

このエリアというのは、NavMeshAgent毎に特定のエリアしか移動できないようにすることができる機能です。

また、エリア毎にコスト(Cost)というものを設定することができ、このコストの値が高くなればなるほど、移動しにくいエリアと判定され、経路探索の際にそのエリアを使われにくくすることもできます。

エリアの設定を行う際は、「Open Area Settings…」を選択することで、

以下のようにエリアのNameCostを指定できます。

Generate Links:オフメッシュリンクの自動生成を行うどうか

Generate Linksは、NavMeshのデータを作る際に、オフメッシュリンクを自動生成するかどうかを決めている項目です。

このGenerate Linksにチェックが入っている場合は、前述したDrop HeightJump Distanceの値に応じて、オフメッシュリンクが自動的に作られるようになります。

例えば、以下のように少し離れたオブジェクトのNavMeshデータを作る際に、Generate Linksにチェックを入れておくと、自動的にオフメッシュリンクが生成されて、NavMeshAgentがそこを移動できるようになります。

Use Geometry:どの形状データでNavMeshを作るか

Use Geometryは、NavMeshのデータを作る際に、どの形状のデータを使って作るかを決めている項目です。

このUse Geometryでは、以下の2つから選択することができます。

  • Render Meshes:Mesh RendererやSkinned Mesh Rendererのデータを使用する
  • Physics Colliders:Colliderコンポーネントのデータを使用する

Collect Objects:どのオブジェクトでNavMeshを作るか

Collect Objectsは、NavMeshのデータを作りたいオブジェクトを指定する項目で、以下の4つから選択することができます。

  • All Game Objects:全てのアクティブなオブジェクトが対象
  • Volume:バウンディングボリュームが重なっているオブジェクトが対象
  • Current Object Hierarchy:現在の階層内にあるアクティブなオブジェクトが対象
  • NavMeshModifier Component Only:NavMesh Modifierが紐づいているオブジェクトが対象

Include Layers:どのレイヤーのオブジェクトでNavMeshを作るか

Include Layersは、NavMeshのデータを作りたいオブジェクトのレイヤーを指定する項目になっています。

先ほどのCollect Objectsで指定したオブジェクトから、さらにレイヤーを使って除外するような場合に、このInclude Layersで指定します。

Override Voxel Size:ボクセルサイズをオーバーライドして設定する

Override Voxel Sizeは、NavMeshのデータを作る際のボクセルサイズを、オーバーライドして手動で設定することができる項目です。

NavMeshデータの作成時にボクセル化というものが行われていて、このボクセルの大きさによってNavMeshの正確さが表されることになります。

特に、狭い通路や段差などはそのままだとNavMeshに上手く反映されないことがあり、その際にこのボクセルサイズを手動で小さくしてあげることで、より正確なNavMeshデータを作ることができます。

ただし、ボクセルサイズを小さくすると、その分メモリの使用量が増えるため、注意しておきましょう。

Override Tile Size:タイルサイズをオーバーライドして設定する

Override Tile Sizeは、NavMeshデータのタイルサイズを、オーバーライドして手動で設定することができる項目です。

NavMeshデータのタイルとは、以下のようにベイクした後に白線で分かれている部分のことで、デフォルトでは「256」となっています。

Minimum Region Area:NavMeshの最小領域の大きさ

Minimum Region Areaは、NavMeshのデータを作る際の最小領域を指定することができる項目です。

このMinimum Region Areaよりも小さい領域では、NavMeshデータを作らないようになります。

Build Height Mesh:Agentを正確に配置させるかどうか

Build Height Meshは、NavMeshAgentを正確に配置することができる設定になっています。

例えば、以下のように階段をNavMeshで作っていた場合に、NavMeshAgentが階段ではなく斜面のように移動してしまうことがあります。

このような場合に、Build Height Meshにチェックを入れてベイクすると、NavMeshAgentが階段を昇り降りしているように移動してくれます。

ただし、メモリの消費量が増えることにはなるため、注意しておきましょう。

Nav Mesh Data:NavMeshデータの管理

Nav Meshのデータファイルを表している部分で、Clearを押すとファイルが削除され、Bakeを押すとベイク処理が行われて、Nav Meshデータが新たに生成されて保存されます。

まとめ

このページでは、UnityのNavMeshSurfaceについて、どんな機能なのか、また使い方や設定方法までをまとめていきましたが、いかがでしたでしょうか?

NavMeshSurfaceとは、AI Navigationのシステムで使われるコンポーネントで、NavMeshAgentが移動できる範囲を指定する役割があります。

このNavMeshSurfaceを使って、NavMeshデータを作ることで、そのデータに沿ってNavMeshAgentが自動で経路探索して移動するようになります。

ただし、NavMeshデータを作る際は、事前にベイク処理を行う必要があるため、基本的にゲームの途中で範囲を変更したりすることができないため、注意しましょう。

最後までお読みいただきまして、ありがとうございました!

コメント