71.NavMeshObstacle导航网格障碍物组件

71.导航寻路系统-导航网格动态障碍组件


71.1 知识点

导航网格动态障碍组件用来干啥

在游戏中常常会有这样的一个功能,场景中有一道门,如果这道门没有被破坏是不能自动导航到门后场景的。
只有当这道门被破坏了,才可以通过此处前往下一场景。
而类似这样的物体本身是不需要进行寻路的,所以没有必要为它添加NavMeshAgent脚本。
这时就会使用动态障碍组件实现该功能。

导航动态障碍物组件的使用

为需要进行动态阻挡的对象添加NavMeshObstacle组件

创建一个立方体作为障碍物,目标是障碍物被销毁才能通过桥。立方体添加NavMeshObstacle组件

设置NavMeshObstacle相关参数

代码逻辑控制障碍物的移动或者显隐,让代理对象看看要不要通过某些区域或者不然通过某些区域


Shape 动态障碍的形状

  • Capsule:胶囊
  • Box:盒装

Carve 切割 是否开启雕刻功能

  • 开启后,障碍物会在导航网格中挖一个孔,所谓挖孔就是会生成对应的网格信息,认为这篇区域无法前往,孔就是障碍物的意思,挖了孔就无法经过了。
  • 如果动态障碍物是固定不动的,建议开启,比如阻碍物门木桶栅栏等等。
  • 如果动态障碍物是频繁移动的,建议不开启该功能,比如汽车和玩家。
Move Threshold 移动阈值
  • 当障碍物移动超过该距离时,会认为其为移动状态,会更新移动的孔。
Time To Stationary 静止时间
  • 障碍物作为静止状态需要等待的时间,单位为秒。
  • 当静止时间超过该值会认为真正静止了。
Carve Only Stationary 仅在静止时切割
  • 只有在静止状态时才会计算孔。


71.2 知识点代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;

public class Lesson71_导航寻路系统_导航网格动态障碍组件 : MonoBehaviour
{
    private NavMeshAgent navMeshAgent;
    
    void Start()
    {
        #region 知识点一 导航网格动态障碍组件用来干啥?
        //在游戏中常常会有这样的一个功能
        //场景中有一道门,如果这道门没有被破坏是不能自动导航到门后场景的
        //只有当这道门被破坏了,才可以通过此处前往下一场景
        //而类似这样的物体本身是不需要进行寻路的所以没有必要为它添加NavMeshAgent脚本
        //这时就会使用动态障碍组件实现该功能
        #endregion

        navMeshAgent = this.GetComponent<NavMeshAgent>();

        #region 知识点二 导航动态障碍物组件的使用
        //1.为需要进行动态阻挡的对象添加NavMeshObstacle组件
        //2.设置相关参数
        //3.代码逻辑控制其的移动或者显隐
        #endregion
    }
    
    void Update()
    {
        if(Input.GetMouseButtonDown(0))
        {
            RaycastHit hit;
            if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out hit))
            {
                navMeshAgent.SetDestination(hit.point);
            }
        }
    }
}

71.3 练习题

在上一个练习题的基础上,在场景上加入一个阻碍玩家前进的动态障碍物,玩家摧毁它才可以前往下一个区域

创建两个地形,中间的桥。桥上添加一个立方体作为障碍物,障碍物添加NavMeshObstacle组件。注意要打开雕刻功能。打开后因为中间寻路网格断开了,玩家会自动停止不播跑步动画了。假如是移动的怪物就不应该打开雕刻功能,注意玩家可以绕开怪物走。

给障碍物立方体修改成Wall层级,在脚本中添加鼠标右键销毁障碍物的代码

if (Input.GetMouseButtonDown(1)) // 如果按下鼠标右键
{
    RaycastHit hit; // 定义一个RaycastHit变量,用于存储射线检测的结果
    if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out hit, 1000, 1 << LayerMask.NameToLayer("Wall"))) // 从主摄像机的鼠标位置发出一条射线,并在1000米内检测到属于Wall层的碰撞体
    {
        hit.collider.gameObject.SetActive(false); // 将碰撞体所在的游戏对象设置为不激活状态,相当于消除障碍物
    }
}

71.4 练习题代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;

public class Lesson71_练习题 : MonoBehaviour
{
    #region 练习题一
    //在上一个练习题的基础上,在场景上加入一个阻碍玩家前进的动态障碍物,玩家摧毁它才可以前往下一个区域

    private NavMeshAgent navMeshAgent; // 定义一个NavMeshAgent变量,用于存储导航代理组件
    private Animator animator; // 定义一个Animator变量,用于存储动画控制器组件
    
    void Start()
    {
        navMeshAgent = this.GetComponent<NavMeshAgent>(); // 获取当前游戏对象上的NavMeshAgent组件并赋值给navMeshAgent变量
        animator = this.GetComponent<Animator>(); // 获取当前游戏对象上的Animator组件并赋值给animator变量
    }
    
    void Update()
    {
        if (Input.GetMouseButtonDown(0)) // 如果按下鼠标左键
        {
            RaycastHit hit; // 定义一个RaycastHit变量,用于存储射线检测的结果
            if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out hit)) // 如果从主摄像机的鼠标位置发出一条射线,并检测到碰撞体
            {
                print(hit.collider.name); // 在控制台输出碰撞体的名称
                navMeshAgent.SetDestination(hit.point); // 设置导航代理的目标位置为碰撞点的位置,导航代理会自动计算并沿着路径移动
            }
        }

        if (Input.GetMouseButtonDown(1)) // 如果按下鼠标右键
        {
            RaycastHit hit; // 定义一个RaycastHit变量,用于存储射线检测的结果
            if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out hit, 1000, 1 << LayerMask.NameToLayer("Wall"))) // 从主摄像机的鼠标位置发出一条射线,并在1000米内检测到属于Wall层的碰撞体
            {
                hit.collider.gameObject.SetActive(false); // 将碰撞体所在的游戏对象设置为不激活状态,相当于消除障碍物
            }
        }

        if (navMeshAgent.velocity == Vector3.zero) // 如果导航代理的速度为零,表示没有移动
            animator.SetInteger("Speed", 0); // 设置动画控制器中的Speed参数为0,表示播放静止动画
        else // 否则,表示正在移动
            animator.SetInteger("Speed", 1); // 设置动画控制器中的Speed参数为1,表示播放行走动画
    }

    #endregion
}


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com

×

喜欢就点赞,疼爱就打赏