で主人公キャラクターをクリックした位置に移動させる事が出来ました。
細かく移動先を指定する事は出来たものの、途中に障害物がある場合、その先の地点をクリックしても壁に突入して移動が出来ません。
途中に障害物があってもそれを避けてクリックした位置に移動するような機能を作る場合ナビゲーション機能が便利です。
ナビゲーションエージェントの設定
今回はナビゲーション機能を主人公に取りつけクリックした位置に障害物を避けながら移動するキャラクターにします。
移動スクリプトは前述した『Unityでマウスクリックした位置にキャラクターを移動させる方法』の記事で使用した物を改造しますのでそちらを参照してください。
またナビゲーション機能に関しては
を参照してください。
主人公キャラを選択し、インスペクタからAdd Component→Navigation→Nav Mesh Agentを選択して追加してください。
Agent Size
Radius、Heightはエージェントのサイズ、コライダと同じような感じです。
Base OffsetはRadius、Heightとキャラクターのオフセット?謎
Steering
Speedはエージェントの最高速度、一番速く移動する時のスピードです。
AngularSpeedは曲がる時のキャラクターの回転の最高速度
Accelerationは最高加速度、数値を高くすると走りだし等で一気に加速します。
Stopping Distanceは目的地にどれだけ近づいたら止めるか
Auto Brakingはチェックを入れると目的地で止まります。チェックしないと止まらずずっと動き続けます。
Obstacle Avoidance
QualityはNavMeshObstacleを設定したゲームオブジェクトとの避け方の品質
Priorityはエージェントの優先度、自分より優先度の低いものを無視して回避します。
PathFinding
Auto Traverse OffMesh Linkはオフメッシュリンク(ナビゲーションのワープポイントみたいなもの)を自動で移動するかどうか
Auto Repathはチェックを入れると部分的な終了地点到達時に再度経路を探索します。到達不可能な経路に来た時に違う経路を探してくれる?
Area Maskはエージェントが移動出来る場所を指定します。
エージェントが移動出来るエリア(地面)を作成
ナビゲーションエージェントを取りつけた主人公キャラが移動出来るエリアを作成します。
フィールドや坂等キャラクターが移動できる地面のゲームオブジェクトのインスペクタのStaticにチェックを入れます。
上の画像のように地面にあたるゲームオブジェクトすべてのStaticにチェックを入れます。
上のようにNavigationタブを表示させます(Unityメニュー→Window→Navigation)。
画像ではインスペクタが上から下まで長くなってしまって全部を表示するのがためらわれました。
・・下の方にBakeボタンがあるので押します。
Agent Radius、Agent Heightはエージェントの範囲です。
Max Slopeはエージェントが昇れる坂の角度
Step Heightは昇れる段差の高さ
Drop Height、Jump Distanceはオフメッシュリンクを自動で生成する時に落ちる高さと横の距離を指定出来ます。
オフメッシュリンク(地続きでない場所を移動する機能)は自分でも作成出来ます。
自動で生成する場合はObjectタブでGenerate OffMeshLinksのチェックを入れます。
主人公をナビゲーション機能を使って動かすNavMoveスクリプトを作成
ナビゲーションエージェント(主人公)が歩ける場所が出来たので次は主人公がマウスクリックされた位置に移動するNavMoveスクリプトを作成します。
Unity5.5バージョン?以降でC#でスクリプトを記述している場合は
using UnityEngine.AI;
というusingディレクティブを入れておくといいです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | using UnityEngine; using System.Collections; public class NavMove : MonoBehaviour { // アニメータコントローラ private Animator animator; // レイを飛ばす距離 private float rayRange; // 移動する位置 private Vector3 targetPosition; // マウスクリックで位置を決めるか [SerializeField] private bool isMouseDownMode; // ナビゲーションエージェント private NavMeshAgent agent; void Start () { animator = GetComponent<Animator>(); rayRange = 100f; targetPosition = transform.position; agent = GetComponent<NavMeshAgent>(); agent.SetDestination(targetPosition); } void Update () { // マウスクリックまたはmouseDownModeがOffの時マウスの位置を移動する位置にする if(Input.GetButtonDown("Fire1") || !isMouseDownMode) { Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); RaycastHit hit; if(Physics.Raycast(ray, out hit, rayRange, LayerMask.GetMask ("Field"))) { targetPosition = hit.point; agent.SetDestination(targetPosition); } } // 目的地に近付いたら走るアニメーションをやめる if(agent.remainingDistance < 0.1f){ animator.SetFloat("Speed", 0f); } else { animator.SetFloat("Speed", agent.desiredVelocity.magnitude); } } } |
キャラクターをクリックした方向に向けたり、CharacterControllerを使って移動させる必要がなくなるので、スクリプトがかなり簡潔になります。
ただ移動経路を探索するので処理が多くなります。
スクリプトが出来たのでキャラクターに設定します。
これでマウスクリックした位置にキャラクターが動くようになります。
isMouseDownModeにチェックを入れない場合はマウスクリックしなくてもマウスの位置に移動しますが、処理負荷がかなり大きくなります。
アニメーターコントローラの設定が終わってない方は
を参照して作成してください。
ナビゲーション機能とマウスクリックで移動が出来るか確認する
これでナビゲーション機能とマウスクリックで移動の機能が完成したので
Unityの実行ボタンを押して確認してみましょう。
上のように坂をクリックすると坂の横にぶつからず迂回して坂を昇るようになりました。
途中にBakeされた障害物があればそれを回避して目的地に移動します。
ナビゲーション機能で注意しなければいけないのは、ゲームオブジェクトのStaticにチェックを入れてBakeしたものの上しか移動しない事です。
途中にBakeしていない障害物等があると通り抜けてしまいます。
またBakeする前に移動する地面のゲームオブジェクトにはFieldレイヤーを設定しておきます。
ナビゲーションエージェントが障害物、移動出来る場所として認識するにはStaticにチェックを入れてBakeする必要があります。
Staticにチェックを入れると他のなんたらStaticにもチェックが入ります。
なんたらStaticを個別で指定したい場合はチェックボックスの横の↓記号の所をクリックして個別にチェックを入れます。
また動くゲームオブジェクトを障害物として認識(敵キャラ等が動く障害物にあたる)したい場合はNavMeshObstacleを使う必要があります。
NavMeshObstacleに関しては
を参照してください。
これでキャラクターがナビゲーション機能を使って頭のいい動きをしてくれるようになりました。
この機能を使えば遠くの地点をクリックして移動先を指定したとしてもナビゲーション機能で移動経路を探索し最適な経路で移動してくれます。
これは非常に便利ですね!