シリーズ記事ディレクトリ
Navemesh 経路探索シリーズの記事
序文
Navemesh はゲームで広く使用されていますが、パスファインディングのほとんどは SetDestination 関数を使用して移動するターゲット ポイントを与えており、移動の一人称直接制御に関する記事はほとんどありません。
この問題を解決するために、この記事を公開します。
这篇博客主要使用NavMeshPath,通过得到移动数组,最终实现正确移动。
1. NavMeshPath とは?
ナビゲーション システムによって計算されたルート。
パスは、コーナー配列に格納されたウェイポイントのリストとして表されます 。これらのウェイポイントはユーザー スクリプトによって直接設定されませんが、 NavMesh.CalculatePath 関数と NavMeshAgent.path プロパティは、正しいウェイポイントが割り当てられた NavMeshPath を返します。
コーナー | パスのコーナー ポイント。(読み取り専用) |
スターテス | パス状態。(読み取り専用) |
2.ステップを使用する
1. ライブラリのインポート
コードは以下のように表示されます:
using UnityEngine;
using UnityEngine.AI;
2. データの読み取り
コードは次のとおりです (例)。
NavMeshAgent.CalculatePath(_pos, m_NavMeshPath);
ここで、navemesh へのパスファインディング パスを取得できます。
次に、ディスプレイスメントを使用してポイント間を移動します.現在の書き込み方法は、上り坂や下り坂などの凹凸のあるマップに適用できます.
完全なコードは次のとおりです。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
/// <summary>
/// 人物平滑移动器
/// </summary>
public class AgentMove : MonoBehaviour
{
public float speed = 0.5f;
// Start is called before the first frame update
void Start()
{
NavMeshAgent = transform.gameObject.GetComponent<NavMeshAgent>();
m_NavMeshPath = new NavMeshPath();
}
private NavMeshAgent NavMeshAgent;
private NavMeshPath m_NavMeshPath;
/// <summary>
/// 前一个路径点索引
/// </summary>
private int m_previousIndex = 0;
/// <summary>
/// 后一个路径点索引
/// </summary>
private int m_currentIndex = 1;
private bool isUpdate = false;
void GetNav(Vector3 _pos)
{
isUpdate = true;
Debug.LogError(transform.position + " " + _pos);
transform.LookAt(_pos);
//计算NavMeshPath
NavMeshAgent.CalculatePath(_pos, m_NavMeshPath);
//初始化路径点索引
m_previousIndex = 0;
m_currentIndex = 1;
//if (m_NavMeshPath.corners.Length>1)
//transform.position = m_NavMeshPath.corners[m_CurrentPathPointIndex];
//Debug.Log(m_NavMeshPath.corners[m_CurrentPathPointIndex]+" "+ m_NavMeshPath.corners.Length);
}
/// <summary>
/// 移动到目标点(NavMeshPath.corners第0个路径点是当前游戏物体所在位置,以此类推)
/// </summary>
public void RunToTarget()
{
isUpdate = m_currentIndex <= m_NavMeshPath.corners.Length - 1;
//防止数组越界
if (!isUpdate) return;
var _pos = transform.position;
_pos.y = m_NavMeshPath.corners[m_currentIndex].y;
//如果游戏物体坐标与当前路径点坐标距离小于0.1即可认为已抵达,可以向下一个路径点导航
if ((_pos - m_NavMeshPath.corners[m_currentIndex]).magnitude <= 0.1f)
{
//递增路径点索引
m_previousIndex++;
m_currentIndex++;
//防止数组越界
if (m_currentIndex > m_NavMeshPath.corners.Length - 1)
{
//Debug.LogError(m_NavMeshPath.corners[m_CurrentPathPointIndex]);
//处理动画切换,请无视
return;
}
//处理人物转向,请无视
}
//匀速运动。计算出前一个路径点到当前路径点方向,然后移动
transform.Translate(
((-m_NavMeshPath.corners[m_previousIndex] +
m_NavMeshPath.corners[m_currentIndex]).normalized) *
(/*Time.deltaTime **/ speed/* *2f*/), Space.World);
Debug.Log(transform.position + " " + m_NavMeshPath.corners[m_currentIndex]);
}
public void Update()
{
var _fx = 1;
if (Input.GetKey(KeyCode.W))
{
GetNav(transform.position + Vector3.forward * _fx);
}
if (Input.GetKey(KeyCode.A))
{
GetNav(transform.position - Vector3.right * _fx);
}
if (Input.GetKey(KeyCode.S))
{
GetNav(transform.position - Vector3.forward * _fx);
}
if (Input.GetKey(KeyCode.D))
{
GetNav(transform.position + Vector3.right * _fx);
}
if (Input.GetKeyUp(KeyCode.W) || Input.GetKeyUp(KeyCode.A) || Input.GetKeyUp(KeyCode.S) || Input.GetKeyUp(KeyCode.D))
{
isUpdate = false;
}
//开始导航
if(isUpdate)RunToTarget();
}
}
効果のスクリーンショットを実現します。
移動はWASDで制御。
要約する
以上が今日お話しする内容ですが、この記事では NavMeshPath の使い方を簡単に紹介するだけで、NavMeshPath にはデータをすばやく簡単に処理できる関数やメソッドが多数用意されています。(Tucao~公式まとめ)