Unity使用NaveMesh实现第一人称视角移动

系列文章目录

Navemesh寻路系列文章



前言

navemesh已经大量使用到游戏中,但大部分寻路都是使用SetDestination函数,给予一个目标点移动,第一人称直接操控移动的文章很少。

为了解决这个问题,特此出了这篇文章。


这篇博客主要使用NavMeshPath,通过得到移动数组,最终实现正确移动。

一、NavMeshPath是什么?

由导航系统计算的路径。

路径以路标列表的形式表示,存储在 corners 数组中。这些路标不是由用户脚本直接设置的,但 NavMesh.CalculatePath 函数和 NavMeshAgent.path 属性会返回分配有正确路标的 NavMeshPath。

corners 路径的角点。(只读)
status 路径状态。(只读)

二、使用步骤

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提供了大量能使我们快速便捷地处理数据的函数和方法。(吐槽下~官方总结)

猜你喜欢

转载自blog.csdn.net/Tel17610887670/article/details/127862079
今日推荐