Navigation System in Unity
Navigation System 在寻路的时候,需要让你的人物直到上楼梯或者跳跃沟渠.
NavMesh system由下面几部分组成:
- NavMesh ( Navigation Mesh的缩写) 是一个描述游戏世界可行走表面的数据结构,并允许在游戏世界中寻找从一个可行走路径到另一个可行走路径. 它在你关卡生成的时候自动构建或者烘焙的
- NavMesh Agent组件:帮助你创建一个可以躲避障碍的人物,从而走向它的目标点. 多个Agents可以直到自己躲避自己
- Off-Mesh Link 组件:可以合并那些表面上没有连接的地面. 比如:跳过一条沟或者一个栅栏,打开一个门
- NavMesh Obstacle 组件:创建一个agent在寻路时应该躲避的障碍. 它们通过物理系统来控制,有物理反应,agent可以根据它位置的变化,得到到达目的地的不同路径
Inner Workings of the Navigation System
当人物自动寻找路径到大目的地的时候有两个问题: 一个是如何找到目的地,第二个就是如何到达目的地. 这两个问题是紧密联系的,但本质上是不同的.如何找到目的地需要考虑整个场景,具有全局性和静态性. 如何移动到目的地具有动态性和局部性 local and dynamic, 它仅仅考虑移动的方向和如何避免和其它移动的人物发生碰撞
Walkable Areas
Navigation System需要自己的数据来表示场景中可以行走的区域. 可行走区域定义了场景中代理可以站立和移动的位置. 在 Unity 中,agent被表示成圆柱体. 可步行区域是通过测试代理可以站立的位置,从场景中的自动构建的几何图形. 然后这些位置被连接到场景中几何图形顶部的表面. 这个表面叫做 navigation mesh(NavMesh 是她的缩写).
NavMesh 将此表面存储为凸多边形. 在一个多边形内的任何两点之间都没有障碍物. 除了多边形边界之外,我们还存储哪些多边形是彼此相邻的信息. 这使我们能够对整个可步行区域进行推理。
Finding Paths
为了找到场景中两个位置之间的路径,我们首先需要将起点和终点位置映射到它们最近的多边形. 然后我们开始搜索从开始的位置,访问所有的邻居,直到我们到达目的地多边形. 通过跟踪访问的多边形,我们可以找到从起点到终点的多边形序列. 使用的是 A* (pronounced “A star”),算法
Following the Path
描述从起点到终点的路径的多边形序列称为走廊 corridor. The agent要到达目的地,始终转向下一个可见corridor角落 . 如果你有一个简单的游戏,在场景中只有一个代理(agent)在移动,你可以一下子找到走廊的所有角落,并让角色沿着连接这些角落的线段移动
在处理多个同时移动的代理时,它们需要在避免彼此时偏离原来的路径. 使用由线段组成的路径来纠正这些偏差就会变得非常困难,而且容易出错。
因为agent在每一帧中的移动量很小,我们可以利用多边形的连通性来固定走廊,以防我们需要绕道 . 然后我们很快就找到了下一个可见的角落。
Avoiding Obstacles
转向逻辑采取下一个角落的位置,并基于此计算出所需的方向和速度(或速度),以达到目的地. 使用期望的速度移动代理可能会导致与其他代理的碰撞。
避障选择了一种新的速度,它可以在朝着期望的方向移动和防止未来与其他智能体和导航网格边缘的碰撞之间取得平衡. Unity 利用速度互反障碍(RVO)来预测和防止碰撞。 reciprocal velocity obstacles (RVO) .
Moving the Agent
最后,在转向和避障后计算出最终速度. Unity使用一个简单的动态模型来模拟这些代理,该模型还考虑了加速度,以允许更自然、更平稳的运动。
在这个阶段你可以把模拟出来的速度,放到animation系统里面,通过root motion 移动agent,或者使用 navigation system
一旦使用任何一种方法移动了代理,模拟的代理位置就开始移动并约束到 NavMesh. 最后一小步对于健壮的导航非常重要
Global and Local
关于导航,需要了解的最重要的事情之一是全局导航和本地导航之间的区别。
Global navigation是来寻找路径,这往往需要花费很多资源和内存
描述路径的线性多边形列表是一种灵活的转向数据结构,可以根据agent的位置移动进行局部调整.本地导航试图找出如何有效地移动到下一个角落,而不与其他代理或移动对象发生冲突。
Two Cases for Obstacles
许多导航应用程序需要其他类型的障碍,而不仅仅是其他代理. 这些可能是射击游戏中常见的板条箱和桶,或者是车辆. 使用 local obstacle avoidance or global pathfinding来避障
当障碍物移动时,最好使用局部避障 local obstacles. 通过这种方式,代理可以预测地避免障碍. 当障碍物静止时,可以认为是阻塞了所有agent的路径, 障碍物应该影响全局导航 global navigation,
改变导航网叫做雕刻 NavMesh is called carving. 这个过程检测障碍接触NavMesh的哪些部分,并在NavMesh上凿洞. 这是一个计算上昂贵的操作,这是另一个令人信服的原因,为什么移动的障碍应该使用避碰来处理。
局部避碰也可以用来避开稀疏的障碍物。由于该算法是局部的,它只考虑接下来的直接冲突,不能绕过陷阱或处理障碍物阻塞路径的情况. 这些案件可以用雕刻来解决
Describing Off-mesh Links
导航网格多边形之间的连接是用寻路系统内部的链接来描述的. 有时有必要让代理在不能行走的地方导航,例如,跳过篱笆,或穿过一个关闭的门。这些案例需要知道操作的位置。
这些操作可以使用Off-Mesh链接进行注释,它告诉pathfinder有一条路径通过指定的链接。这个链接可以在以后按照路径访问,并且可以执行特殊的操作。
Building a NavMesh
创建 NavMesh 的过程称为 NavMesh Baking. 该过程收集所有被标记为Navigation Static的游戏物体或地形,然后对它们进行处理,创建一个近似于水平面的可行走表面的导航网格
In Unity, NavMesh 通过 Navigation window (menu: Window > AI > Navigation).来生成
为你的场景建立一个NavMesh可以通过4个快速步骤完成::
- Select 选择场景中要烘焙成nav mesh的物体
- Check Navigation Static勾选上Navigation Static
- Adjust 调整烘焙设置
- Agent Radius 定义代理中心到墙或壁架的距离
- Agent Height agent的高度.
- Max Slope 定义agent可以走的斜坡
- Step Height 定义代理可以踩到的障碍物的高度。.
- Click bake to build the NavMesh.
正如你在上面的图片中所注意到的,在生成的NavMesh中可行走的区域似乎缩小了. NavMesh表示代理中心可以移动的区域,这和你的agent radius有关. 从概念上讲,无论您将代理看作是缩小的NavMesh上的一个点还是全尺寸NavMesh上的一个圆,这两者都是等价的
另一件需要记住的事情是NavMesh是可行走表面的近似. 这可以在楼梯上看到,它被表示为一个平面,而源表面有台阶. 这样做是为了保持NavMesh数据的小尺寸.这种近似的副作用是,有时你需要在关卡几何中留出一些额外的空间来允许代理通过一个紧点。 The side effect of the approximation is that sometimes you will need to have a little extra space in your level geometry to allows the agent to pass through a tight spot.
烘焙完成之后, 你会发现在资源文件夹下有一个和场景名一样的文件夹,里面存放 NavMesh数据. 例如,如果在Assets文件夹中有一个名为First Level的场景, the NavMesh will be at Assets > First Level > NavMesh.asset.
Additional Workflows for Marking Objects for Baking
除了在导航窗口中将对象标记为导航静态之外 Navigation Static in the Navigation Window‚ 如上所述,您可以使用检查器顶部的静态菜单
Further Reading
- Creating a NavMeshAgent – learn how to allow your characters to move.
- Bake Settings – full description of the NavMesh bake settings.
- Areas and Costs – learn how to use different Area types.
NavMesh building components
NavMesh building 组件提供了额外烘焙导航网格的方法,可以在运行或者编辑器状态下使用
下面列出的高级NavMesh构建组件并没有提供标准的Unity编辑器安装程序,你可以从Unity store下载. 也可以从 Unity Technologies GitHub 单独安装它们 下载网址: GitHub - Unity-Technologies/NavMeshComponents: High Level API Components for Runtime NavMesh Building
这些组件的使用必须相互结合,比如modifier和volume的使用,必须基于surface使用,原生态的和这些组件是两个独立的系统
有四个高级组件可供使用 NavMesh:
-
NavMesh Surface - 用于为一种类型的代理构建和启用NavMesh表面。.
-
NavMesh Modifier - 基于物体的层级,影响导航网格的类型的生成
-
NavMeshModifierVolume - 基于体积,影响导航网格的生成
-
NavMeshLink - 为一种类型的agent,连接不同或相同的导航网格表面
See also documentation on Mesh-BuildingComponents-API.
For more information on Agent types, refer to documentation on creating NavMesh Agents.
For more details about NavMesh area types, see documentation on NavMesh areas.
Creating high-level NavMesh building components
To install the high-level NavMesh building components:
-
Download and install Unity 5.6 or later.
-
Clone or download the repository from the NavMesh Components page on the Unity Technologies GitHub by clicking on the green Clone or download button.
-
Open the NavMesh Components Project using Unity, or alternatively copy the contents of the Assets/NavMeshComponents folder to an existing Project.
Find additional examples in the Assets/Examples folder.
Note: Make sure to back up your Project before installing high-level NavMesh building components.
NavMesh Surface
NavMesh Surface 表示场景中的可行走区域
添加 GameObject> AI > NavMesh Surface. 一个场景可以包含多个 NavMesh Surfaces.
你可以为任何游戏物体添加 NavMesh Surface 组件.
Property | Function |
---|---|
Agent Type | - Humanoid - Ogre |
Collect Objects | 定义烘焙的类型 - All – Use all active GameObjects (this is the default option). - Volume – 使用所有活动的游戏物体重叠的包围体,就是如果有重叠的物体,使用的是外轮廓. - Children – 含有 NavMesh Surface component.组件的子物体 |
Include Layers | - Nothing (automatically unticks all other options, turning them off) - Everything (automatically ticks all other options, turning them on) - Default - TransparentFX - Ignore Raycast - Water - UI |
Use Geometry | 选择烘焙使用的几何图形。 - Render Meshes – Render Meshes 和 Terrains - Physics Colliders– Colliders 和 Terrains.与使用Render Meshes选项相比,使用此选项的代理可以更接近环境的物理边界。 |
微调几何体使用: NavMesh Modifier component.
烘焙过程会自动排除带有NavMesh代理或NavMesh障碍的游戏对象.他们是NavMesh的动态用户,所以不参与NavMesh的构建
Advanced settings
The Advanced settings section allows you to customize the following additional parameters:
Property | Function |
---|---|
Default Area | 定义在构建NavMesh时生成的区域类型。 - Walkable (this is the default option) - Not Walkable - Jump Use the NavMesh Modifier component to modify the area type in more detail. |
Override Voxel Size | 控制Unity处理NavMesh烘焙输入几何图形的精度(这是速度和精度之间的折衷)).选中tickbox以启用。默认为未选中(禁用)。 3体素每剂半径(6每直径)允许捕获狭窄的通道,如门,同时保持一个快速烘烤时间。对于大的开放区域,使用1或2体素每半径加速烘焙。紧凑的室内点更适合较小的体素,例如每半径4到6个体素。每个半径超过8个体素通常不会提供更多的好处。 |
Override Tile Size | 为了使烘焙过程并行且记忆效率高,场景被划分为多个小块进行烘焙。NavMesh上可见的白线是平铺的边界。 默认的块大小是256个体素,这在内存使用和NavMesh碎片之间提供了一个很好的权衡。 要更改这个默认的平铺大小,请选中此复选框,并在平铺大小字段中输入您希望平铺大小的体素数量。 瓦片越小,NavMesh就越碎片化。这有时会导致非最优路径。NavMesh雕刻也适用于瓷砖。如果你有很多障碍 |
Build Height Mesh | Not supported. |
NavMesh Modifier
NavMesh Modifiers 在烘焙的时候调整具体的游戏物体的烘焙网格 NavMesh
添加 NavMesh Modifier component, GameObject> AI > NavMesh Modifier.
NavMesh Modifier 根据层级起作用,影响它所有的子物体,如果在在物体上发现一个同样的组件,则新组件重写旧组件
NavMesh Modifier 修改的地方,在生成navmesh的时候都要考虑进去
Property: | Function: |
---|---|
Ignore From Build | 不烘焙该物体 |
Override Area Type | 选中此复选框以更改包含修饰符及其所有子元素的GameObject(游戏对象)的区域类型。 |
Area Type | 区域类型 |
Affected Agents | 影响的角色,可以为单独的游戏角色创建一个nav mesh |
NavMesh Modifier Volume
NavMesh Modifier Volume 将定义的区域标记为某个类型 (for example, Lava or Door). NavMesh Modifier 是给游戏物体标记一个类型. NavMesh Modifier Volume 可以根据不同的区域标记类型,不是单个游戏物体
添加 NavMesh Modifier Volume , GameObject> AI > NavMesh Modifier Volume.
NavMesh Modifier Volume他标记的是单个区域,比如下面的拖拽的区域,标记为Door
A NavMesh Modifier Volume component open in the Inspector window
Property | Function |
---|---|
Size | NavMesh Modifier Volume的大小 |
Center | NavMesh Modifier Volume 的中心点 |
Area Type | Describes the area type to which the NavMesh Modifier Volume applies. - Walkable (this is the default option) - Not Walkable - Jump |
Affected Agents | 选择影响的角色 - None - All (this is the default option) - Humanoid - Ogre |
NavMesh Link
NavMesh Link 在使用NavMeshes的两个位置之间创建一个可导航的链接。就是连接两个不相邻的网格,它是同一个nav mesh的不同的点
连接是点到点,也可以跨越一个间隙,角色从入口边缘最近的点跨越连接
你必须用NavMesh Link 连接不同的 NavMesh Surfaces.
GameObject> AI > NavMesh Link.
A NavMesh Link component open in the Inspector window
Property | Function |
---|---|
Agent Type | The Agent type that can use the link. - Humanoid - Ogre |
Start Point | 连接得起点, relative to the GameObject. Defined by XYZ measurements. |
End Point | 连接得终点,relative to the GameObject. Defined by XYZ measurements. |
Align Transform To Points | 将游戏物体,起点和终点,移动到连接得中心点 |
Bidirectional | 双向连接,启用之后,方向是双向的,从起点到终点,从终点到起点,不启用,默认只从起点到终点 |
Area Type | The area type of the NavMesh Link (this affects pathfinding costs). - Walkable (this is the default option) - Not Walkable - Jump |
Connecting multiple NavMesh Surfaces together
Note that when connecting NavMesh Surfaces:
-
You can connect NavMesh Surfaces using multiple NavMesh Links.
-
NavMesh Surfaces 和NavMesh Link必须有一样的Agent type.
-
The NavMesh Link’s start and end point must only be on one NavMesh Surface - be careful if you have multiple NavMeshes at the same location.
-
如果你正在加载第二个NavMesh表面,而你在第一个场景中有未连接的NavMesh链接,请检查它们没有连接到任何不想要的NavMesh表面。
NavMesh building components API
NavMeshSurface
Properties
agentTypeID
– 描述角色的idcollectObjects
– 场景中需要烘焙的物体的类型 Scene
, one ofUnityEngine.AI.CollectObjects:
All
– 场景中所有的物体,只要是标记了nav static 的都参加烘焙Volume
–在 bounding volume内的物体(seesize
andcenter
)Children
– NavMesh Surface 组件下的子物体
size
– 定义烘焙的体积,和缩放没关系center
– 烘焙体积的中心点layerMask
– Bitmask defining the layers on which the GameObjects must be to be included in the baking.useGeometry
– Defines which geometry is used for baking, one ofUnityEngine.NavMeshCollectGeometry
:RenderMeshes
– Use geometry from render meshes and terrainsPhysicsColliders
– Use geometry from colliders
and terrains
.
defaultArea
– Default area type for all input geometries, unless otherwise specified.ignoreNavMeshAgent
– True if GameObjects with a Nav Mesh Agent component should be ignored as input.ignoreNavMeshObstacle
– True if GameObjects with a Nav Mesh Obstacle component should be ignored as input.overrideTileSize
– True if tile size is set.tileSize
– Tile size in voxels(the component description includes information on how to choose tile size).overrideVoxelSize
– True if the voxel size is set.voxelSize
– Size of the voxel in world units (the component description includes information on how to choose tile size).buildHeightMesh
– Not implemented.bakedNavMeshData
– Reference to the NavMeshData the surface uses, or null if not set.activeSurfaces
– List of all active NavMeshSurfaces.
Note: 设置完之后,调用 Bake()更新
.
Public Functions
void Bake ()
Bakes a new NavMeshData based on the parameters set on NavMesh Surface. 烘焙的数据可以通过 bakedNavMeshData
.属性访问
NavMesh Modifier
Properties
overrideArea
– True if the modifier overrides area type.area
– New area type to apply.ignoreFromBuild
– True if the GameObject which contains the modifier and its children should be not be used to NavMesh baking.activeModifiers
– List of all active NavMeshModifiers.
Public Functions
bool AffectsAgentType(int agentTypeID)
Returns true if the modifier applies to the specified Agent type, otherwise false.
NavMesh Modifier Volume
Properties
size
– Size of the bounding volume in local space units. Transform affects the size.center
– Center of the bounding volume in local space units. Transform affects the center.area
– Area type to apply for the NavMesh areas that are inside the bounding volume.
Public Functions
bool AffectsAgentType(int agentTypeID)
Returns true of the the modifier applies for the specified Agent type.
NavMesh Link
Properties
agentTypeID
– The type of Agent that can use the link.startPoint
– Start point of the link in local space units. Transform affects the location.endPoint
– End point of the link in local space units. Transform affects the location.width
– 连接的宽度,可以是一条线,也可以是一个面.bidirectional
– If true, the link can be traversed both ways. If false, the link can be traversed only from start to end.autoUpdate
– If true, the link updates the end points to follow the transform of the GameObject every frame.area
– Area type of the link (used for pathfinding cost).
Public Functions
void UpdateLink()
.当起点或者终点改变位置时,就需要更新连接,可以打开autoUpdate
属性,如果没有打开的话,调用该方法UpdateLink
,毕竟这个不怎么耗性能
Advanced NavMesh Bake Settings
Min Region Area
The Min Region Area advanced 可以剔除小的非链接区域,凡是小于这个值的都被剔除掉,不烘焙
但是有些情况却不能剔除, The NavMesh 是一个平面网格. 如果一个区域跨越一个平铺边界,则该区域不被移除.这样做的原因是,区域修剪发生在构建过程的某个阶段,此时周围的块是不可访问的。
Voxel Size
Manual voxel size allows you to change the accuracy at which the bake process operates.
The NavMesh bake process uses voxelization to build the NavMesh from arbitrary level geometry. In the first pass of the algorithm, the scene
is rasterized into voxels, then the walkable surfaces are extracted, and finally the walkable surfaces are turned into a navigation mesh
. The voxel size describes how accurately the resulting NavMesh represents the scene geometry.
The default accuracy is set so that there are 3 voxels per agent radius, that is, the whole agent width is 6 voxels. This is a good trade off between accuracy and bake speed. Halving the voxel size will increase the memory usage by 4x and it will take 4x longer to build the scene.
Generally you should not need to adjust the voxel size, there are two scenarios where this might be necessary: building a smaller agent radius, or more accurate NavMesh.
Smaller Agent Radius
When you bake for an artificially smaller agent radius, the NavMesh bake system will also reduce the voxel size. If your other agent dimensions stays the same, it may not be necessary to increase the NavMesh build resolution.
The easiest way to do that is as follows:
- Set the Agent Radius to the real agent radius.
- Turn on the Manual Voxel Size, this will take the current voxel size and “freeze it”.
- Set the artificially smaller Agent Radius, since you have checked on the Manual Voxel Size the voxel size will not change.
More Accurate NavMesh
If your level has a lot of tight spots, you may want to increase the accuracy by making the voxel smaller. The label under the Voxel Size shows the relation between the voxel size and Agent Radius. A good range is something between 2–8, going further than that generally results really long build times.
When you intentionally build tight corridors in your game, please note that you should leave at least 4 * voxelSize clearance in addition to the agent radius, especially if the corridors are at angles.
If you need smaller corridors than the NavMesh baking can support, please consider using Off-Mesh Links. These have the additional benefit that you can detect when they are being used and can, for example, play a specific animation.
Creating a NavMesh Agent
烘焙好导航网格之后,就可以添加角色导航了
First let’s create the character:
- 创建一个圆柱体,当作角色: GameObject > 3D Object > Cylinder.
- 默认height 2 and radius 0.5
- 给它添加 NavMesh Agent 组件: Component > Navigation > NavMesh Agent.
当你开始试验NavMesh代理时,你很可能会根据你的角色大小和速度来调整它的尺寸
NavMesh Agent 能够控制角色的移动和寻路. 在脚本当中,声明寻路的终点
// MoveTo.cs
using UnityEngine;
using UnityEngine.AI;
public class MoveTo : MonoBehaviour {
public Transform goal;
void Start () {
NavMeshAgent agent = GetComponent<NavMeshAgent>();
agent.destination = goal.position;
}
}
下一步,我们需要建立一个简单的脚本,让你发送你的角色到目的地:
- Create a new C# script (
MoveTo.cs
) and replace its contents with the above script. - Assign the MoveTo script to the character you’ve just created.
- Create a sphere, this will be the destination the agent will move to.
- Move the sphere away from the character to a location that is close to the NavMesh surface.
- 通过 Goal 属性声明目的地
- Press Play; you should see the agent navigating to the location of the sphere.
Creating a NavMesh Obstacle
NavMesh Obstacle 来创建一个障碍物, 比如,角色应该避免物理系统控制的对象,就是有碰撞体的,这是另一种方法添加障碍物
这个方法是独立于烘焙网格之外的,也就是这个不用烘焙,可以是动态的物体
- 创建一个cube: Game Object > 3D Object > Cube.
- 给他 添加NavMesh Obstacle component 组件
- 设置障碍物的形状
- 添加一个 Rigid body 组件.
- 打开 NavMesh Obstacle inspector属性面板的Carve 属性
Creating an Off-mesh Link
. 它连接两个不相邻的表面,例如,跳过沟渠或篱笆,或在穿过之前打开一扇门
我们将添加一个Off-Mesh链接组件来描述从上层平台到地面的跳跃
- 创建两个圆柱体: Game Object > 3D Object > cylinder.
- 把第一个圆柱体移动到平台顶端的边缘
- 第二个放置在地面上second cylinder on the ground, close to the NavMesh, at the location where the link should land.
- 给其中一个圆柱添加Off-Mesh Link 组件Navigation > Off Mesh Link.
- 把这两个圆柱赋给start 和end的值.
任何游戏物体都可以添加 Off-Mesh link组件. 你也可以把任何物体当作起点和终点
Building Off-Mesh Links Automatically
一些情况可以使用 Off-Mesh Links 自动生成连接网格
- Drop-Down 跳下
- Jump-Across 跳上
I为了自动找到跳转位置,构建过程沿着NavMesh的边缘走,并检查跳转的着陆位置是否在NavMesh上。如果跳转轨迹是畅通无阻的,则会创建一个离网链接。
在 Navigation Window 窗口下的Object一栏,勾选上Generate Off-Mesh Links
第二步是设置下拉和跳跃轨迹:
- Drop-Down:通过 Drop Height 参数控制,需要注意的是:场景中需要跳下的高度,要比这个值大,否则只会往下走,而不是跳下
- Jump-Across :跳上,场景中的高度要比这个小,才能跳上
Building Height Mesh for Accurate Character Placement
Height mesh 可以让角色更加精确的在导航网格上行走
NavMesh Agent 被导航网格约束 NavMesh,因为 NavMesh 是是一个平面的近似值,比 :在导航网格中,楼梯被烘焙成一个斜面,如果你想更精确一些,打开 Height Mesh 烘焙. Note that building Height Mesh会稍微消耗一点内存和烘焙时间
Navigation Areas and Costs
Navigation Areas define 定义了通过一个区域所花费的价值,耗费的价值越低,在选择路径是就更优先选择. 除此之外, 每一个 NavMesh Agent 都有一个 Area Mask 用来指定可以移动的区域
在上面的例子中,区域类型用于两个常见的用例:
- Water 为了应对在浅水区行走速度较慢的情况,该区域的步行成本较高。
- Door特定的角色可以进入该区域,创建一个人类可以通过门而僵尸不能通过的场景。
在 NavMesh baking烘焙的时候,可以为每个游戏物体声明它的area type ,这可以通过添加modify组件来完成,给需要的游戏物体添加modify,重写它的area,声明独有的类型,除此之外,每一个 Off-Mesh Link 也都有区域类型
Pathfinding Cost
简而言之,成本允许您控制寻路者在寻找路径时喜欢的区域。例如,如果您将某个区域的成本设置为3.0,则穿越该区域的时间将被认为是选择其他路线的三倍长。
要完全理解成本是如何工作的,让我们来看看pathfinder是如何工作的。
Unity 使用 A* 算法计算导航网格 NavMesh. A* 是一对节点. 该算法从距离路径起点最近的节点开始,访问连接节点,直到到达目的地。
:因为Unity的导航表示是一个多边形的网格,所以pathfinder需要做的第一件事就是在每个多边形上放置一个点,也就是节点的位置。然后计算这些节点之间的最短路径。
上图中的黄色点和线显示了节点和链接是如何放置在NavMesh上的,以及它们在A*中被遍历的顺序。
在两个节点之间移动的成本取决于移动的距离和与链接下多边形的面积类型相关的成本,即距离*成本。在实践中,这意味着,如果一个区域的成本是2.0,那么穿过该多边形的距离将是原来的两倍。A*算法要求所有代价都大于1.0。.
成本对最终路径的影响很难调整,特别是对于较长的路径。处理成本的最好方法是把它们当作提示. 例如,如果您希望代理不要太频繁地使用Off-Mesh,则可以增加它们的成本。但是,要调整代理更喜欢在人行道上行走的行为是很有挑战性的。
另一件事,你可能会注意到,在某些程度上,探路者并不总是选择最短的路径。这样做的原因是节点的位置。这种效果在大的开放区域旁边有小的障碍物的情况下是很明显的,这就导致了导航网格有很大和很小的多边形。在这种情况下,大多边形上的节点可能被放置在大多边形的任何地方,从探路者的角度来看,它看起来像是一个迂回的路线。
area type的价值cost可以通过 Areas tab, 或者通过脚本来控制:
一共可以声明29中area type和cost,有三种内置的type: Walkable, Not Walkable, and Jump.
- Walkable 是一个泛型区域类型,它指定可以在该区域上行走。.
- Not Walkable 在这上面不可以走.可以标记一个障碍物
- Jump 对自动生成的 Off-Mesh Links.的物体的类型
如果不同区域类型的多个对象重叠,则得到的navmesh区域类型通常是索引最高的那个. Not Walkable总是优先
每一个agent 都有Area Mask 表示那些区域可以通过. The area mask 可以通过 agent 属性设置
这在为不同类型的游戏物体,通过不同类型的区域的设置当中有用
Loading Multiple NavMeshes using Additive Loading
不同场景中的 NavMeshes默认是不连接的. 当你使用Application.LoadLevelAdditive()加载另一个场景时,你需要使用一个Off-Mesh link来连接不同场景中的NavMeshes .
比如Scene 1 and Scene 2. The Scene 1有一个Off-Mesh Link 从场景一开始,跨越到场景2.根据需要,可以有尽可能多的Off-Mesh Links来连接场景
When authored the other end point of the scene connecting Off-Mesh links are not connected. After a new Scene is loaded, the Off-Mesh Links will be reconnected.
如果多个场景在同一区域有NavMesh重叠,则该位置的拾取可能是任意的NavMesh. This applies to agents, Off-Mesh Links and position picking using the NavMesh API. 起点和终点不能覆盖
Using NavMesh Agent with Other Components
NavMesh Agent, NavMesh Obstacle, and Off Mesh Link 可以和其它组件一起使用
NavMesh Agent and Physics
- NavMesh Agents 不用添加collider
- 也就是说,导航系统模拟了agent及其对障碍物和静态世界的反应.
- 如果NavMesh Agent 推动物理对象或使用physics triggers:
- 添加 Collider component (if not present)
- 添加 Rigidbody component
- 勾选 kinematic (Is Kinematic) - 这很重要
- Kinematic 意味着刚体不是由物理模拟控制的
- 如果 NavMesh Agent and Rigidbody (non-kinematic没有勾选) 同时打开了, 他俩会矛盾
- Both components may try to move the agent at the same which leads to undefined behavior
- 你可以使用NavMesh代理来移动例如一个玩家角色,而不需要物理机制
- 设置玩家代理的 avoidance priority躲避优先级为小数量(高优先级),允许玩家在人群中穿梭
- Move the player agent using NavMeshAgent.velocity,这样其他代理就可以预测玩家的动作以避开玩家。
NavMesh Agent and Animator
- NavMesh Agent and Animator 有 Root Motion也会造成矛盾
- 这两个组件都试图移动transform
- 两种可能的解决方案
- I信息应该总是朝着一个方向流动
- Either agent moves the character and animations follows
- Or animation moves the character based on simulated result
- Otherwise you’ll end up having a hard to debug feedback loop
- Animation follows agent
- Use the NavMeshAgent.velocity as input to the Animator to roughly match the agent’s movement to the animations
- Robust and simple to implement, will result in foot sliding where animations cannot match the velocity
- Agent follows animation
- Disable NavMeshAgent.updatePosition and NavMeshAgent.updateRotation to detach the simulation from the game objects locations
- Use the difference between the simulated agent’s position (NavMeshAgent.nextPosition) and animation root (Animator.rootPosition) to calculate controls for the animations
- See Coupling Animation and Navigation for more details
NavMesh Agent and NavMesh Obstacle
- 不要混在一起!
- Enabling both will make the agent trying to avoid itself
- If carving is enabled in addition, the agent tries to constantly remap to the edge of the carved hole, even more erroneous behavior ensues
- Make sure only one of them are active at any given time
- Deceased state, you may turn off the agent and turn on the obstacle to force other agents to avoid it
- Alternatively you can use priorities to make certain agents to be avoided more
NavMesh Obstacle and Physics
- 如果你想要物理系统控制的物体,影响 NavMesh Agent的行为
- 给物理系统的物体添加NavMesh Obstacle 组件
- 如果一个物体有 Rigidbody and a NavMesh Obstacle组件,障碍物的速度取自Rigidbody
- 这使得NavMesh代理能够预测和避免移动的障碍物