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.2, 2018.1, 2017.2のブランチいずれか
それ以外: 2017.1, 5.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;
にもどす
Wow Thanks for this thread i find it hard to come across good quality information and facts out there when it comes to this material thank for the article site