前言
Unity 3D导航系统(Navigation) Unity 3D Navigation(导航)是用于实现动态物体自动寻路的一种技术,它将游戏场景中复杂的结构关系简化为带有一定信息的网格,并在这些网格的基础上通过一系列相应的计算来实现自动寻路。
过去,游戏开发者必须自己打造寻路系统,特别是在基于节点的寻路系统中,必须手动地在 AI 使用的点之间进行导航,因此基于节点系统的寻路非常烦琐。
Unity 3D 不仅具有导航功能,还使用了导航网格(navigation meshes),这比手动放置节点更有效率而且更流畅。
更重要的是,还可以一键重新计算整个导航网格,彻底摆脱了手动修改导航节点的复杂方法。
提示:以下是本篇文章正文内容
Unity AI(Navigation)导航系统🤖🤖🤖
种类
NavMeshAgent类
描述
导航网格代理。
此组件附加到游戏中的某个移动角色,以允许该角色使用导航网格在场景中导航
一、属性、变量、方法
- 变量
属性名 | 作用 |
desiredVelocity | 代理的期望速度,包括来自规避的任何潜在贡献。(只读) |
velocity✔ | 获取 NavMeshAgent 瞬时速度,或者设置一个速度来手动控制代理。 |
velocity.magnitude | 打印向量的膜。 |
nav.velocity.sqrMagnitude | 返回该向量的平方长度。(只读) |
speed | 遵循路径时的最大移动速度。 |
isStopped | 导航停止还是恢复。 |
destination | 获取目标点。 |
stoppingDistance | 停止距离。 |
remainingDistance ✔ | 剩余距离。(只读) |
areaMask | 指定走哪条路,-1(全选),(2^(选几个-1)) |
isOnOffMeshLink | 是否处于分离式导航?(只读) |
updatePosition | 获取或设置变换位置是否与模拟的代理位置同步。默认值为 true(通过导航更新的位置)。 |
updateRotation | 代理是否应该更新变换方向(通过导航更新的旋转)? |
✔ | |
acceleration | 代理遵循某一路径时的最大加速度,以单位/秒^2 表示。 |
agentTypeID | 代理的类型 ID。 |
angularSpeed | 遵循路径时的最大回转速度(以 deg/s 为单位)。 |
autoBraking | 代理是否应自动制动以避免越过目标点? |
autoRepath | 如果现有路径失效,代理是否应尝试获取新的路径? |
autoTraverseOffMeshLink | 代理是否应自动跨越 OffMeshLink? |
avoidancePriority | 规避优先级别。 |
baseOffset | 拥有 GameObject 的相对垂直位移。 |
currentOffMeshLinkData | 当前的 OffMeshLinkData。 |
hasPath | 代理当前是否有路径?(只读) |
height | 代理高度(为了从障碍物下穿过,等)。 |
isOnNavMesh | 代理当前是否绑定到导航网格?(只读) |
isPathStale | 当前路径过时了吗?(只读) |
navMeshOwner | 返回当前放置代理的导航网格所属的对象(只读)。 |
nextOffMeshLinkData | 当前路径上的下一个 OffMeshLinkData。 |
nextPosition | 获取或设置导航网格代理的模拟位置。 |
obstacleAvoidanceType | 规避品质级别。 |
path | 获取和设置当前路径的属性。 |
pathPending | 是正在计算过程中而尚未就绪的路径吗?(只读) |
pathStatus | 当前路径的状态(完整、部分或无效)。 |
radius | 代理的规避半径。 |
steeringTarget | 获取路径中的当前转向目标。(只读) |
updateUpAxis | 您可以用来指定代理是否应与导航网格的向上轴或者它所在的链接对齐。 |
- 公共函数
属性名 | 作用 |
SetDestination | 设置导航的目标 如:.SetDestination(Vector 3) |
CalculatePath | 计算到指定点的路径并存储生成的路径(返回ture) 如:nav.CalculatePath(目标位置, NavMeshPath) 。 |
获取拐点 |
|
💤 | 💤 |
ActivateCurrentOffMeshLink | 启用或禁用当前的网格外链接。 |
CompleteOffMeshLink | 完成在当前 OffMeshLink 上的移动。 |
FindClosestEdge | 找到最近的导航网格边缘。 |
GetAreaCost | 获取在跨越特定类型的区域时的路径计算成本。 |
Move | 将相对移动应用于当前位置。 |
Raycast | 在导航网格中跟踪一条直线路径到达目标位置,而无需移动代理。 |
ResetPath | 清除当前路径。 |
SamplePathPosition | 沿着当前路径对某一位置进行取样。 |
SetAreaCost | 设置遍历此类型区域的成本。 |
SetPath | 为此代理分配一条新路径。 |
Warp | 将代理调整至指定的位置。 |
- 继承的成员公共函数
- 静态函数
二、基本使用
- 引入命名空间:using UnityEngine.AI;
- 勾选静态导航
2. 烘培
3. Player舔加NavMeshAgent组件
4. 创建一个目标位置
5. 设置目标位置:NavMeshAgent.SetDestination(Vector 3);
6. 代码展示:🛬🛬🛬🛬🛬🛬
```代码
public Transform tran;
privateNavMeshAgentnav; voidStart () { nav=GetComponent<NavMeshAgent>(); } voidUpdate () { nav.SetDestination(tran.position); }
- Player 身上的三个箭头
红色: 指向(阶段性目标)
蓝色: (阶段性期望速度)
黑色: (瞬时速度)
三、分离路面导航🤾♀️
普通分离路面
设置分离路面静态
设置方法:选中两个Plane路面,然后选中Off Mesh Link Generation(有两种选择的方法);
分离路面跳跃设置
设置方法:选中面板Navigation->Bake->(DorpHeight(只能从高跳到低)/JumpDistance(双向跳跃)(前提是两个地面的高低差不多))
高级分离路面
舔加offMeshLink组件(挂在两点其中一点上)
使用:
创建两个点分别放在地面的两端
然后拖给offMeshLink组件
选择路线导航
选中要导航的路线
- 舔加Areas名称(给两条路选上名称)
- 选择要导航的路线名称
- 选择要导航的路线名称
- 代码实现选导航路线
nav.areaMask获取对应层的编号
编号的计算公式2^n-1 (n为第几层)
如:选中4层 :2^3-1 - 例子:
navs=GetComponent<NavMeshAgent>(); navs.areaMask=16;
选中的是第五层公式是2^5-1=16
四、堵墙
给障碍物舔加组件:NavMeshObstacle组件
五、Trail组件
六、Line组件
说明:线渲染器用于在 3D 空间中绘制自由浮动的线。
变量:
变量 | |
alignment | 选择线是朝向摄像机还是变换组件的方向。 |
colorGradient | 设置颜色渐变,用于描述线在其长度上各个点处的颜色。 |
endColor | 设置线终点处的颜色。 |
endWidth | 设置线终点处的宽度。 |
generateLightingData | 配置线以生成法线和切线。借助此数据,场景光照可以通过法线贴图和 Unity 标准着色器或是您自己的定制着色器来影响线。 |
loop | 将线的起点和终点位置连接在一起,以形成连续循环。 |
numCapVertices | 将它设置为大于 0 的值,可在线的每端上获得圆角。 |
numCornerVertices | 将它设置为大于 0 的值,可在线的每个细分段之间获得圆角。 |
positionCount | 设置/获取顶点数。 |
shadowBias | 应用阴影偏差以防止自我阴影瑕疵。指定的值是每一段的线宽比例。 |
startColor | 设置线起点处的颜色。 |
startWidth | 设置线起点处的宽度。 |
textureMode | 选择线纹理的 U 坐标是进行平铺还是拉伸。 |
useWorldSpace | 如果启用,则在世界空间中定义线。 |
widthCurve | 设置曲线,用于描述线在其长度上各个点处的宽度。 |
widthMultiplier | 设置一个整体乘数,它应用于 LineRenderer.widthCurve 以获取线的最终宽度。 |
公共函数:
使用鼠标在屏幕画线小案例
代码演示:
privateboolisDown; privateboolisUp; privateboolcurrenIsDown; privateboolcurrenIsUp; privateVector3curren; privateVector3startPos; privateVector3endPos; privateLineRendererline; privateintlineDo; privateVector3[] Postion=newVector3[10]; privatefloatlineTime; voidStart() { line=GetComponent<LineRenderer>(); } voidUpdate() { curren.x=Input.mousePosition.x; curren.y=Input.mousePosition.y; currenIsDown=false; currenIsUp=false; isDown=Input.GetMouseButton(0); if (isDown&&!isUp) currenIsDown=true; if (!isDown&&isUp) currenIsUp=true; isUp=isDown; if (currenIsDown||isDown) { startMove(); } } voidstartMove() { startPos=curren; vara=Camera.main.ScreenToWorldPoint( newVector3(startPos.x,startPos.y,10)); varb=Camera.main.ScreenToWorldPoint( newVector3(endPos.x, endPos.y,10)); if (Vector3.Distance(a, b) >0.1f) { lineDo++; settingOut(); sendLinePosion(); } endPos=curren; lineTime-=Time.deltaTime; if (lineTime<0) { lineDo++; settingOut(); lineTime=0.1f; } } voidsettingOut() { if (lineDo<=9) { for (inti=lineDo; i<=9; i++) { Postion[i] =Camera.main.ScreenToWorldPoint(newVector3(curren.x, curren.y, 10)); } } else { for (intj=0; j<=8; j++) { Postion[j] =Postion[j+1]; } Postion[9] =Camera.main.ScreenToWorldPoint(newVector3(curren.x, curren.y, 10)); } } ///<summary>///将保存的点添加到line上///</summary>privatevoidsendLinePosion() { inti=0; foreach (Vector3iteminPostion) { line.SetPosition(i, item); i++; } }
NavMesh类
描述
用于访问烘焙导航网格的单例类。
NavMesh 是一个类,可用于执行空间查询(如寻路和步行性测试)、设置特定区域类型的寻路成本以及调整寻路和规避的整体行为。
静态变量:
变量名 | 作用 |
SamplePosition | 在指定范围内找到导航网格上最近的点。P1 |
✔ |
AllAreas | 包含所有导航网格区域的区域遮罩常量。 |
avoidancePredictionTime | 描述代理在未来多久后预测碰撞,以便进行规避。 |
onPreUpdate | 设置一个要在执行帧更新期间且在导航网格更新之前调用的函数。 |
pathfindingIterationsPerFram | 异步寻路过程中每帧处理的最大节点数。 |
静态函数 | |
AddLink | 向导航网格添加链接。此链接由 NavMeshLinkData 结构描述。 |
AddNavMeshData | 戏添加指定的导航网格数据。 |
CalculatePath | 两点之间的路径并存储生成的路径。 |
CalculateTriangulation | 计算当前导航网格的三角形剖分。 |
CreateSettings | 创建并返回可用于运行时导航网格构建操作的导航网格构建设置新条目。 |
FindClosestEdge | 从导航网格上的一点找到最近的导航网格边缘。 |
GetAreaCost | 获取区域类型几何体的寻路成本。 |
GetAreaFromName | 返回名为导航网格区域类型的区域索引。 |
GetSettingsByID | 返回导航网格构建设置的现有条目。 |
GetSettingsByIndex | 按其有序索引返回导航网格构建设置的现有条目。 |
GetSettingsCount | 返回已注册的导航网格构建设置的数量。 |
GetSettingsNameFromID | 返回与导航网格构建设置(与提供的代理类型 ID 匹配)关联的名称。 |
Raycast | 在导航网格上的两点之间找出一条线。 |
RemoveAllNavMeshData | 从游戏中删除所有导航网格表面和链接。 |
RemoveLink | 从导航网格中删除链接。 |
RemoveNavMeshData | 从游戏中删除指定的 NavMeshDataInstance,使其无法用于代理和查询。 |
RemoveSettings | 删除与代理类型 ID 匹配的构建设置。 |
SetAreaCost | 设置所有代理上的区域类型几何体的寻路成本。 |
委托:
代码:
P1NavMeshHithit; NavMesh.SamplePosition(目标点, outhit, 范围, layer) ?enemyRandomPoint : transform.position; 作用说明:在指定范围内找到导航网格上最近的点,如果找到就就执行enemyRandomPoint函数(自己创建的🙃)返回一个随机的坐标继续导航,如果没找到就是他自己的位置,就不会导致卡障碍物的旁边。