69.导航寻路系统-导航网格寻路组件
69.1 知识点
NavMeshAgent导航网格代理是用来干什么的
通过上节课导航网格生成知识点的学习,我们已经准备好了地形相关的数据,知道地形上哪些地方可以到达,哪些不能。那么寻路组件的作用就是帮助我们让角色可以在地形上准确的移动起来。
寻路组件的本质就是根据烘焙出的寻路网格信息,通过基于A星寻路的算法计算出行进路径让我们在该路径上移动起来。
NavMeshAgent导航网格代理组件参数
Agent Type 代理类型 配合Agents页签使用
Base Offset 基础偏移值 相对对象轴心点的高度偏移 其实就是改圆柱体位置
Steering 转向 移动设置
- Speed 寻路时的最大移动速度(世界单位/秒)
- Angular Speed 寻路时转身的最大旋转速度(度/秒)
- Acceleration 最大加速度(世界单位/平方秒)
- Stopping Distance 当靠近目标点多少距离时,停止运动
- Auto Braking 自动制动(减速)
- 启用后,当到达目标时将减速,如果存在连续移动(比如巡逻移动)建议不要开启该选项。
Obstacle Avoidance 障碍躲避 避障设置
- Radius 半径,用于计算障碍物和其它寻路对象之间的碰撞
- Height 高度,通过头顶障碍物时用于计算高度间隙使用
- Quality 障碍躲避品质
- 越高躲避障碍越准确,但是性能消耗较大。
- 如果不想主动避开其它动态障碍,可以设置为无,则只会解析碰撞。
- Priority 优先级
- 0~99,避障时,数字较小的障碍物表示较高的优先级。
- 优先级低的会忽略避障。
Path Finding 寻路 路径寻找规则
Auto Traverse OffMesh Link 自动通过分离网格连接
- 是否开启自动遍历网格外的其它网格连接。
- 如果要自定义判断,则关闭此功能。
Auto Repath 自动重新寻路
- 是否开启自动重设路线。
- 如果开启,当到达路径后段时会再次尝试寻路,当没有到达目标的路径时,会生成一条到达与目标位置最近的可达点
- 默认勾选。
Area Mask 寻路时考虑的区域
- 如果寻路时不想考虑某些区域,则取消选中。
- 塔防游戏中常见的功能。
NavMeshAgent导航网格代理代码控制
使用网格相关脚本需要引用命名 UnityEngine.AI
常用内容
NavMeshAgent.SetDestination方法 自动寻路设置目标点传入Vector3变量
//NavMeshAgent中的SetDestination方法 自动寻路设置目标点 传入Vector3变量
//设置或更新目标,从而触发新路径计算。
//navMeshAgent.SetDestination()
NavMeshAgent.isStopped变量 停止寻路
//NavMeshAgent中的isStopped变量 停止寻路
//此属性持有导航网格代理的停止或恢复条件。
//navMeshAgent.isStopped = true;
Update中的示例
void Update()
{
if (Input.GetMouseButtonDown(0)) // 如果按下鼠标左键
{
RaycastHit hit; // 定义一个RaycastHit变量,用于存储射线检测的结果
if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out hit)) // 如果从主摄像机的鼠标位置发出一条射线,并检测到碰撞体
{
print(hit.collider.name); // 在控制台输出碰撞体的名称
navMeshAgent.isStopped = false; // 设置导航代理的isStopped属性为false,表示可以移动
//让对象朝目标点移动 先生成行进路径 然后再移动
navMeshAgent.SetDestination(hit.point); // 设置导航代理的目标位置为碰撞点的位置,导航代理会自动计算并沿着路径移动
}
}
if (Input.GetKeyDown(KeyCode.Space)) // 如果按下空格键
{
navMeshAgent.isStopped = true; // 设置导航代理的isStopped属性为true,表示停止移动
}
}
注意
- 假如发现跳跃的地方跳不过去,需要检查两岸的生成寻路网格连接的选项有没有勾选,要勾选了才能从一边跳到另一边,要两边都能跳的话两边都要勾选
- 遇到消耗更高的区域会绕着走
- 不勾选对应区域就不会走到对应区域上
不常用内容
NavMeshAgent.speed变量 速度
//NavMeshAgent中的speed变量 速度
//遵循路径时的最大移动速度。
print(navMeshAgent.speed);
NavMeshAgent.acceleration变量 加速度
//NavMeshAgent中的acceleration变量 加速度
//代理遵循某一路径时的最大加速度,以单位/秒^2 表示。
print(navMeshAgent.acceleration);
NavMeshAgent.angularSpeed变量 旋转速度
//NavMeshAgent中的angularSpeed变量 旋转速度
//遵循路径时的最大回转速度(以 deg/ s 为单位)。
print(navMeshAgent.angularSpeed);
NavMeshAgent.hasPath变量 当前是否有路径
//NavMeshAgent中的hasPath变量 当前是否有路径
//代理当前是否有路径?(只读)
if ( navMeshAgent.hasPath )
{
}
NavMeshAgent.destination变量 代理目标点 可以设置也可以得到
//NavMeshAgent中的destination变量 代理目标点 可以设置 也可以得到
//获取代理在世界坐标系单位中的目标或尝试设置代理在其中的目标。
print(navMeshAgent.destination);
NavMeshAgent.isStopped变量 停止寻路
//NavMeshAgent中的isStopped变量 停止寻路
//此属性持有导航网格代理的停止或恢复条件。
print(navMeshAgent.isStopped);
NavMeshAgent中.path变量 当前路径
//NavMeshAgent中的path变量 当前路径
//获取和设置当前路径的属性。
print(navMeshAgent.path);
NavMeshAgent.pathPending变量 路径是否在计算中
//NavMeshAgent中的pathPending变量 路径是否在计算中
//是正在计算过程中而尚未就绪的路径吗?(只读)
if ( navMeshAgent.pathPending )
{
}
NavMeshAgent.pathStatus变量 路径状态
//NavMeshAgent中的pathStatus变量 路径状态
//当前路径的状态(完整、部分或无效)。
print(navMeshAgent.pathStatus);
NavMeshAgent.updatePosition变量 是否更新位置
//NavMeshAgent中的updatePosition变量 是否更新位置
//获取或设置变换位置是否与模拟的代理位置同步。默认值为 true。
navMeshAgent.updatePosition = true;
NavMeshAgent.updateRotation变量 是否更新角度
//NavMeshAgent中的updateRotation变量 是否更新角度
//代理是否应该更新变换方向?
navMeshAgent.updateRotation = true;
NavMeshAgent.velocity变量 代理速度
//NavMeshAgent中的velocity变量 代理速度
//获取 NavMeshAgent 组件的当前速度,或者设置一个速度来手动控制代理。
print(navMeshAgent.velocity);
NavMeshAgent.CalculatePath方法 计算生成路径
//NavMeshAgent中的CalculatePath方法 计算生成路径
//计算到指定点的路径并存储生成的路径。
NavMeshPath navMeshPath = new NavMeshPath();
if( navMeshAgent.CalculatePath(Vector3.zero, navMeshPath) )
{
}
NavMeshAgent.SetPath方法 设置新路径
//NavMeshAgent中的SetPath方法 设置新路径
//为此代理分配一条新路径。
if (navMeshAgent.SetPath(navMeshPath))
{
}
NavMeshAgent.ResetPath方法 清除路径
//NavMeshAgent中的ResetPath方法 清除路径
//清除当前路径。
navMeshAgent.ResetPath();
NavMeshAgent.Warp方法 调整到指定点位置
//NavMeshAgent中的Warp方法 调整到指定点位置
//将代理调整至指定的位置。
navMeshAgent.Warp(Vector3.zero);
69.2 知识点代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class Lesson69_导航寻路系统_导航网格寻路组件 : MonoBehaviour
{
public NavMeshAgent navMeshAgent;
void Start()
{
#region 知识点一 导航网格寻路组件是用来干什么的?
//通过上节课导航网格生成知识点的学习
//我们已经准备好了地形相关的数据
//知道地形上哪些地方可以到达,哪些不能
//那么寻路组件的作用就是帮助我们让角色可以在地形上准确的移动起来
//寻路组件的本质就是根据烘焙出的寻路网格信息
//通过基于A星寻路的算法计算出行进路径让我们在该路径上移动起来
#endregion
#region 知识点二 寻路组件参数相关
//导航网格寻路组件
//Nav Mesh Agent(导航网格代理人)
#endregion
#region 知识点三 寻路组件代码相关
//使用网格相关脚本需要引用命名空间
//UnityEngine.AI
#region 常用内容
//NavMeshAgent中的SetDestination方法 自动寻路设置目标点 传入Vector3变量
//设置或更新目标,从而触发新路径计算。
//navMeshAgent.SetDestination()
//NavMeshAgent中的isStopped变量 停止寻路
//此属性持有导航网格代理的停止或恢复条件。
//navMeshAgent.isStopped = true;
#endregion
#region 不常用内容
#region 变量
//关键变量
//面板参数相关
//速度 加速度 旋转速度等等
//NavMeshAgent中的speed变量 速度
//遵循路径时的最大移动速度。
print(navMeshAgent.speed);
//NavMeshAgent中的acceleration变量 加速度
//代理遵循某一路径时的最大加速度,以单位/秒^2 表示。
print(navMeshAgent.acceleration);
//NavMeshAgent中的angularSpeed变量 旋转速度
//遵循路径时的最大回转速度(以 deg/ s 为单位)。
print(navMeshAgent.angularSpeed);
//其它重要属性
//NavMeshAgent中的hasPath变量 当前是否有路径
//代理当前是否有路径?(只读)
if ( navMeshAgent.hasPath )
{
}
//NavMeshAgent中的destination变量 代理目标点 可以设置 也可以得到
//获取代理在世界坐标系单位中的目标或尝试设置代理在其中的目标。
print(navMeshAgent.destination);
//NavMeshAgent中的isStopped变量 停止寻路
//此属性持有导航网格代理的停止或恢复条件。
print(navMeshAgent.isStopped);
//NavMeshAgent中的path变量 当前路径
//获取和设置当前路径的属性。
print(navMeshAgent.path);
//NavMeshAgent中的pathPending变量 路径是否在计算中
//是正在计算过程中而尚未就绪的路径吗?(只读)
if ( navMeshAgent.pathPending )
{
}
//NavMeshAgent中的pathStatus变量 路径状态
//当前路径的状态(完整、部分或无效)。
print(navMeshAgent.pathStatus);
//NavMeshAgent中的updatePosition变量 是否更新位置
//获取或设置变换位置是否与模拟的代理位置同步。默认值为 true。
navMeshAgent.updatePosition = true;
//NavMeshAgent中的updateRotation变量 是否更新角度
//代理是否应该更新变换方向?
navMeshAgent.updateRotation = true;
//NavMeshAgent中的velocity变量 代理速度
//获取 NavMeshAgent 组件的当前速度,或者设置一个速度来手动控制代理。
print(navMeshAgent.velocity);
#endregion
#region 方法
//手动寻路
//NavMeshAgent中的CalculatePath方法 计算生成路径
//计算到指定点的路径并存储生成的路径。
NavMeshPath navMeshPath = new NavMeshPath();
if( navMeshAgent.CalculatePath(Vector3.zero, navMeshPath) )
{
}
//NavMeshAgent中的SetPath方法 设置新路径
//为此代理分配一条新路径。
if (navMeshAgent.SetPath(navMeshPath))
{
}
//NavMeshAgent中的ResetPath方法 清除路径
//清除当前路径。
navMeshAgent.ResetPath();
//NavMeshAgent中的Warp方法 调整到指定点位置
//将代理调整至指定的位置。
navMeshAgent.Warp(Vector3.zero);
#endregion
#endregion
#endregion
}
void Update()
{
if (Input.GetMouseButtonDown(0)) // 如果按下鼠标左键
{
RaycastHit hit; // 定义一个RaycastHit变量,用于存储射线检测的结果
if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out hit)) // 如果从主摄像机的鼠标位置发出一条射线,并检测到碰撞体
{
print(hit.collider.name); // 在控制台输出碰撞体的名称
navMeshAgent.isStopped = false; // 设置导航代理的isStopped属性为false,表示可以移动
//让对象朝目标点移动 先生成行进路径 然后再移动
navMeshAgent.SetDestination(hit.point); // 设置导航代理的目标位置为碰撞点的位置,导航代理会自动计算并沿着路径移动
}
}
if (Input.GetKeyDown(KeyCode.Space)) // 如果按下空格键
{
navMeshAgent.isStopped = true; // 设置导航代理的isStopped属性为true,表示停止移动
}
}
}
69.3 练习题
在上一个练习题的基础上,在场景上加入一个角色,可以通过鼠标右键点击控制场景上角色的移动,要切换动画
创建场景和角色,调整场景为静态烘焙场景。给角色添加代理组件和Animator组件,创建一个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 (navMeshAgent.velocity == Vector3.zero) // 如果导航代理的速度为零,表示没有移动
animator.SetInteger("Speed", 0); // 设置动画控制器中的Speed参数为0,表示播放静止动画
else // 否则,表示正在移动
animator.SetInteger("Speed", 1); // 设置动画控制器中的Speed参数为1,表示播放行走动画
}
69.4 练习题代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI; // 引入导航命名空间
public class Lesson69_练习题 : 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 (navMeshAgent.velocity == Vector3.zero) // 如果导航代理的速度为零,表示没有移动
animator.SetInteger("Speed", 0); // 设置动画控制器中的Speed参数为0,表示播放静止动画
else // 否则,表示正在移动
animator.SetInteger("Speed", 1); // 设置动画控制器中的Speed参数为1,表示播放行走动画
}
#endregion
}
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com