NavMeshの種類をざっくり学ぶ

Navmeshとは

UnityのナビゲーションシステムでプレイヤーやNPCがゲーム内を歩行可能になるデータ構造

詳しくはこちら
https://docs.unity3d.com/ja/2020.3/Manual/nav-NavigationSystem.html

Unity 2020.3で説明していきます。

 

通常のNavMesh

プレイヤーと地面を作成します。

Capsuleオブジェクトをplayerとして作成(色は適当)

PlaneオブジェクトをGroundとして作成

通常のNavmeshを使う場合
歩き回らせたい地面オブジェクトのStaticを有効にします。

メニューからWindows>AI>Navigation

BakeタブからBakeボタンを押すとNavMeshが作成される

青色が歩き回れるエリアになります。

 

ちなみにNavmeshウィンドウがアクティブになってないと青色のエリアは表示されません。

 

これだけでは動かないので、エリア内を動けるように
PlayerオブジェクトにNavmeshAgentコンポーネントをアタッチ

 

移動用スクリプト作成

using UnityEngine;
using UnityEngine.AI;

public class FollowTarget : MonoBehaviour
{
    public Transform target;
    Vector3 destination;
    NavMeshAgent agent;
    
    void Start()
    {
        agent = GetComponent<NavMeshAgent>();
        
        //NavMeshの目的地を設定
        destination = agent.destination;
    }
    
    void Update()
    {
        //Targetと距離が離れたら移動
        if (Vector3.Distance(destination, target.position) > 1.0f)
        {
            destination = target.position;
            agent.destination = destination;
        }
        
        //マウスをクリックした場所に移動
        if(Input.GetMouseButtonUp(0)) {
            RaycastHit hit;
            if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out hit, 100)) {
                agent.destination = hit.point;
            }
        }
    }
}

Playerオブジェクトに移動用スクリプトをアタッチ

cubeをTargetとして作り、設定

 

実行するとPlayerがTargetに向かって移動、

ターゲットを動かすかGroundをクリックすると移動するようになります。

 

この方法だと

・GroundオブジェクトはStaticになっているためゲーム実行中は動かせない

・事前にBakeした範囲しか動くことが出来ない


 

その他のNavmeshを使えるようにする

Navmeshウィンドウから

Leam instead about the component workflow.
(コンポーネントのワークフローについてはこちら)

をクリック

UnityのGithubページに飛びます
https://github.com/Unity-Technologies/NavMeshComponents

 

UnityのバージョンにあったモノをDL
master for 2020.3-LTS, 2019.3 for up to 2019.4-LTS, 2018.3 for up to 2018.4-LTS and 2019.2, 2018.2, 2018.1, 2017.2 for up to 2017.4-LTS, 2017.1, 5.6.

↑この表記、ぱっと見どれがどれに対応してるか分からん・・・
たぶん↓こういうことだと思う。

Unity 2020.3-LTS:マスターブランチ
Unity 2019.4-LTS:2019.3ブランチ
Unity 2018.4-LTSとから2019.2まで:2018.3ブランチ
Unity 2017.4-LTSまで:2018.22018.12017.2のブランチいずれか
それ以外: 2017.15.6.どちらか

 

DLしたファイルを解凍

NavMeshComponents-master\NavMeshComponents-master\Assets以下のフォルダをプロジェクトに入れ込みます。
最低限必要なのはGizmos、NavMeshComponetsフォルダのみ。

 

各サンプルシーンの説明

サンプルシーンは以下にあります。

Assets>Examples>Scenes

1_multiple_agent_sizes
クリックした箇所に移動
赤いAgentは右端のゲートしか通れない(AgentTypeが設定されてないため?)

2_drop_plank

クリックした箇所に移動
スペースを押すと板が落ちてきて渡れる
LocalNavMeshBuilderオブジェクトの同名スクリプトについているサイズ範囲内のものを自動でbakeし直してるっぽい。

3_free_orientation

TiltedPlaneオブジェクトのNavMeshSurfaceコンポーネントでBakeしている。Staticを付ける必要がないためワールド座標ではなくローカル座標でのBakeが可能。オブジェクトを回転させてもNavmeshで移動できる

4_sliding_window_infinite

クリックした箇所に移動
Agentの周りが自動的に移動可能エリアになる
LocalNavMeshBuilderオブジェクトのサイズ範囲内をbakeしなおしてるっぽい。

5_sliding_window_terrain

4とほぼ同じ

6_modify_mesh

地形をリアルタイムで変形

マウスカーソルで合わせたところでクリックすると地形が盛り上がる

右クリックで地形が凹む

7_dungeon

複数のNavmeshをnavmeshlinkを使用して移動可能にしている。

Agentがnavmeshlinkの端に到達するとジャンプする。

7b_dungeon_tile_prefabs

7で使用するprefab群

 


 

関連コンポーネント

NavMeshObstacle

既にBake済みのNavmeshに上書きで移動不可エリアを追加できる。
ただし1オブジェクトに1つしか付けれない。
https://docs.unity3d.com/ja/2020.3/Manual/nav-CreateNavMeshObstacle.html

 

OffMeshLink

複数のNavmeshを接続することが出来る。

Unity標準コンポーネント、NavmeshLinkの前世。
スタート地点とエンド地点をserializefieldのTransfromで指定する必要がある。

 

NavMeshLink

複数のNavmeshを接続することが出来る。

githubから追加されたコンポーネント、offmeshlinkの上位互換

スタート地点とエンド地点をPositionZYXで指定する。
一方通行、双方向通行を選択できる。
Bidirectional:両方向移動する場合にチェック、一方通行の場合はチェックを外す

Widthを0.5とか1とか設定しておかないとNavMeshLink上を移動してくれないので注意

中身はoffmeshLinkなのでスクリプトで制御するときも
agent.currentOffMeshLinkData.endPosのような感じで扱う

https://docs.unity3d.com/ja/2020.3/Manual/class-NavMeshLink.html

 
 
 

NavMeshModifierVolume

https://docs.unity3d.com/ja/2020.3/Manual/class-NavMesh-ModifierVolume.html

事前に範囲を指定しておきBake時にその設定で上書きする。

なので、すでにBakeしてある箇所に後から追加するだけでは反応しない。
(あとから追加したらもう一度Bakeしなおす)

meshがあるオブジェクトじゃないと反応しない。なので空のオブジェクトに設定して上書きしようとしても反応しない。

※プレイヤーの周りだけコストを上げる時に使えるかと思ったけど、NavMeshObstacleみたいにリアルタイムで動くものには使えなかった。

 

 

以下まとめきれてないメモ

 

移動のあれこれ

 
 
agent.SetDestination(position);

 

エリアマスク

areaMaskの設定が公式referenceに乗ってない・・
これはビットフィールドです。とか設定できます。だけ
NavMesh.GetAreaFromNameの方に説明があった 

_agent.areaMask = 1 << NavMesh.GetAreaFromName("Jump");

 

 

navmeshlinkにagentが乗ると速度が上がってしまう。
この問題はスクリプトで制御する必要がある。

参考:https://tsubakit1.hateblo.jp/entry/2016/12/01/031711

 

agentの足元が動く場合

一度agentの移動を全て停止させる
agent.ResetPath();
agent.isStopped = true;
agent.updatePosition = false;
agent.updateRotation = false;

ただし、
agent.updatePosition = false;
agent.updateRotation = false;
の影響でagent本体が置いてきぼりになる

完了処理で
NavMeshAgent.Warp(本体の位置.position);
を読んであげる必要がある

その後
agent.updatePosition = true;
agent.updateRotation = true;
にもどす

 

関連記事




コメントを残す

※コメントは承認後に表示されます。
 コメントを公開されたくない場合、名前の後に「:非公開」とつけてください。