NavMesh.Raycast和NavMesh.CalculatePath的使用

一般情况下,只有主角是需要自动寻路的,其他玩家和怪物位置都是服务器转发过来的。除了主角身上有 NavMeshAgent,其他玩家和怪物对象可以不依赖 NavMeshAgent了,不用自主寻路,服务器直接下发目标点 (走线段),减少性能消耗。

判断是否其他玩家或怪物对象可以直接到达目标点,使用NavMesh.Raycast判断,其他玩家或怪物对象与目标点之间存在障碍物,如果存在,使用NavMesh.CalculatePath重新规划路径。

 

using UnityEngine;
using UnityEngine.AI;

public class NavMeshCalculatPath : MonoBehaviour
{
    public Transform m_TargetTrans;
    private NavMeshAgent m_NavMeshAgent;
    private NavMeshPath m_NavMeshPath;
    private Vector3 m_SourcePos;
    private Vector3 m_TargetPos;
    private float m_Distance;
    private Vector3[] m_WayPoint = new Vector3[30];
    private int m_AreaMask;
    private bool m_ExcuteOne = false;
    private bool m_Finished = false;
    private NavMeshHit m_NavMeshHit;
    private float m_ArrivedDistance = 0.1f;

    void Start()
    {
        m_SourcePos = transform.position;
        m_TargetPos = m_TargetTrans.position;

        int area = NavMesh.GetAreaFromName("Walkable");
        m_AreaMask = 1 << area;
        m_NavMeshPath = new NavMeshPath();

        // 初始化NavMeshAgent
        m_NavMeshAgent = GetComponent<NavMeshAgent>();
        // 设置目标点
        m_NavMeshAgent.destination = m_TargetPos;
        // 如果当前路径无效,尝试获得一个新的路径
        m_NavMeshAgent.autoRepath = true;
        // 自动刹车,不开启可能会在目标点附近来回晃动
        m_NavMeshAgent.autoBraking = true;
        // 规避半径
        m_NavMeshAgent.radius = 0.6f;
        // 规避的质量水平,设定越高,权衡规避障碍的精度越高
        m_NavMeshAgent.obstacleAvoidanceType = ObstacleAvoidanceType.NoObstacleAvoidance;
        // 加速度
        m_NavMeshAgent.acceleration = 10000;
        // 转弯角速度
        m_NavMeshAgent.angularSpeed = 2000;
        // 根据配置来设定速度
        m_NavMeshAgent.speed = 3.5f;
        // 一般实际开发中,方向需要服务器控制,需要设置为false
        m_NavMeshAgent.updateRotation = true;
        // 距离目标位置的停止距离
        m_NavMeshAgent.stoppingDistance = 0.01f;
    }

    void Update()
    {
        if (m_Finished)
        {
            return;
        }
        // m_NavMeshAgent.pathPending 当前路径正在计算
        // m_NavMeshAgent.remainingDistance 当前代理位置和目标位置的距离
        if (!m_NavMeshAgent.pathPending && m_NavMeshAgent.remainingDistance < m_ArrivedDistance)
        {
            Debug.Log("到达目标点");
            m_Finished = true;
        }
        if (m_ExcuteOne)
        {
            return;
        }
        // 如果在当前位置和目标点之间,存在阻碍
        if (NavMesh.Raycast(m_SourcePos, m_TargetPos, out m_NavMeshHit, m_AreaMask))
        {
            // 重新规划路径
            if (NavMesh.CalculatePath(m_SourcePos, m_TargetPos, m_AreaMask, m_NavMeshPath))
            {
                if (m_NavMeshPath.status == NavMeshPathStatus.PathComplete)
                {
                    // 获得路径点的数量
                    int wayPointLength = m_NavMeshPath.GetCornersNonAlloc(m_WayPoint);
                    // 如果路径点的数量超过了数组的长度,那么重新分配
                    if (wayPointLength > m_WayPoint.Length)
                    {
                        m_WayPoint = new Vector3[wayPointLength];
                        m_NavMeshPath.GetCornersNonAlloc(m_WayPoint);
                    }
                    Debug.Log("wayPointLength: " + wayPointLength);
                    for (int i = 0; i < wayPointLength; i++)
                    {
                        Debug.Log("m_WayPoint: " + m_WayPoint[i]);
                    }
                    // 清空所有路径点
                    m_NavMeshPath.ClearCorners();

                    m_ExcuteOne = true;
                }
            }
        }
    }
}

有个简单的Unity例子,可以查看寻路的结果。

NavMeshCaluatePath.unitypackage

链接:https://pan.baidu.com/s/14yj2ofc03YfiQqTey8t8Eg 
提取码:lb7y 
 

  • 1
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值