前言:在游戲中經常出現怪物自己會走路,人物跟隨鼠標點擊位置進行移動,那么這些功能是怎么實現的呢?通過本節內容的學習,你會對自動尋路的原理有一個初步的認識。當然了如果想像英雄聯盟里面的人物那樣帶點擊的特效的話,還需要用到粒子系統方面的知識,好了,廢話不多說了,咱們開始吧
1. 認識網格導航組件
Nav Mesh Agent(網格導航代理)
- Radius:agent的半徑,用于計算該agent和其他agent、obstacle的碰撞。
- Height:agent的高度,agent可以通過的頭頂障礙最小高度。
- Base offset:agent圓柱碰撞體中心點的偏移值。當Agent創建后,圓柱碰撞體顯示過高或過低,用于將其調整到地面。
- Speed:agent移動的最大速度(世界空間中以秒單位計算)
- Angular Speed:agent最大的旋轉速度(角度每秒)
- Acceleration:agent最大的加速度(世界空間單位每秒的平方)
- Stopping distance:agent靠近目標時停下的距離
- Auto Braking:自動剎車,當啟用的時候agent會在到達終點時慢慢停下,你應該在角色需要平滑地巡邏幾個固定點時,禁用它。
- Quality:障礙回避的質量值,如果你有大量的agent就可以降低該值節約CPU的資源,將它設置為0,則只會處理碰撞,不會嘗試規避其他agent和obstacle。
- Priority:agent會重視該值比自己小的,而忽略該值比自己大的。該值范圍為0到99,數字越低意味著高權限,權限越高(越小的值)會被其他agent重視而回避。
- Auto Traverse OffMesh Link:需要agent自動通過off-mesh link的時候設置為true,當想要使用動畫或其他特殊的方法通過off-mesh link時設為false。
- Auto Repath:啟用時,agent會在到達局部路徑的終點時,嘗試再次尋找路徑。當沒有通向目標的路徑時,它會生成一個離目標最近的點作為當前的一個目標。(我嘗試下來發現,當目標點不可達,勾選該選項的agent嘗試尋找臨近目標點的欲望比不勾選的要大)
- Area Mask:AreaMask描述了agent會在哪些烘培的區域中尋找路徑。當你準備烘培NavMesh時,你可以指定區域的類型,比如你想讓階梯作為一個特殊的區域,并且禁止某些角色使用階梯。
在使用Agent的時候,大家可能發現了Agent有Radius屬性,在我們烘培NavMesh的時候設置的圓柱體也有Radius屬性,兩者有什么區別呢?
在尋路的時候有兩個階段,第一階段只考慮烘培NavMesh并尋找一條可行的路徑,而第二階段Agent就已經在前往目的地的路上了,它會考慮其他agent和obstacle,并盡量避開他們。
烘培時候的Radius就對應第一階段的生成NavMesh,而Agent上的Radius只在第二階段使用。就比如說,有一條小徑,你有一只大怪是通過不了該路徑的,但烘培時候的Radius設置的比較小,雖然Agent的Radius可能設置的很大,但這只大怪還是會使用該小徑通過。
所以要理解尋路的兩個階段,再強調一遍,第一階段沒有開始真正的尋路不考慮其他的agent和obstacle,只看NavMesh,而第二階段Agent已經在行走,而會盡量避開其他agent和obstacle。
Off Mesh Link(分離網格連線)
OffMeshLink組件允許你在區域中給Agent提供一些小近路,使Agent能快速通過,比如跳過柵欄、通過一扇門。
- Start:物體描述的開始點。
- End:物體描述的結束點。
- Cost Override:如果該值是正的,使用它在處理需求路徑時計算路徑的代價值,否則會使用默認的代價值(游戲物體所屬區域的代價值)。如果代價值設置超過3.0,經過該off-mesh link會比經過三倍的默認NavMesh區域還多。當你想用Agent初始化偏愛的路徑時,該代價值非常有用。當然最好是在移動中清晰比較長的距離中使用。
- Bi Directional:如果啟用,則該link是雙向的,否則只能從Start到End。
- Activated:指定該link會不會在尋路的時候使用(在設置為false的時候被忽略)
- Auto Update Position:啟用的時候,Off-Mesh Link會自動重新連接start和end的坐標,如果禁用,則只使用啟用時候的坐標,即使后來坐標移動了也不會改變。
- Navigation Area:描述link所屬的NavMesh區域類型,該區域類型會允許你在相似類型區域中應用該區域的通路代價值,并且防止一些特定的Agent使用該通路,使用Agent的AreaMask屬性來控制。
Nav Mesh Obstacle(網格導航障礙)
- Shape:obstacle的幾何形狀,選擇物體最合適的形狀,有兩種Box方塊和Capsule膠囊體。
- Box/Center:方塊形狀的中心點,與Transform的Position有關。
- Box/Size:方塊的大小尺寸。
- Capsule/Center:膠囊體形狀的中心點,與Transform的Position有關。
- Capsule/Radius:膠囊體的半徑。
- Capsule/Height:膠囊體的高度。
- Carve:當Carve該選項被勾選,Obsacle該物體會在NavMesh上制造一個空洞。
- Move Threshold:Unity會在Obstacle移動該距離下,將其處理為移動狀態,使用該屬性設置移動更新Carve空洞的頻率。
- Time To Stationary:Obstacle停止運動后,經過多少時間(秒)會被處理為靜止狀態。
- Carve Only Stationary:啟用時,Obstacle僅會在靜止時被處理成空洞,詳見官方文檔(廢話)。這里有幾個小細節需要注意,禁用該選項時,空洞的重新計算是隔一幀計算一次,就是兩幀計算一次。然后最好啟用該選項,因為每次空洞的重新計算比較費時。官方文檔中舉了兩個適用的場景:木桶、箱子之類會受力停止的啟用選項,而像坦克緩慢移動的,則可以禁用該項。
Navigation面板(導航面板)
Agents(網格導航代理)
- Agent Types:導航代理類型
- Name:導航代理名字
- Radius:導航代理半徑
- Height:導航代理高度
- Step Height:能上去的臺階高度
- Max Slope:最大的坡度
Areas(導航區域)
- 前三個是Unity內置的Walkable(能走的),Not Walkable(不能走的),Jump(跳)
- 其他的用戶用來自定義
Bake(烘焙參數面板)
- Radius:具有代表性的物體半徑,半徑越小生成的網格面積越大。
- Height:具有代表性的物體的高度。
- Max Slope:斜坡的坡度。
- Ste Height:臺階高度。
- Drop Height:允許最大的下落距離。
- Jump Distance:允許最大的跳躍距離。
- Min Region Area:網格面積小于該值則不生成導航網格。
- Width Inaccuracy:允許最大寬度的誤差。
- Height Inaccuracy:允許最大高度的誤差。
- Height Mesh:勾選后會保存高度信息,同時會消耗一些性能和存儲空間。
Object(物體參數面板)
- Navigation Static:勾選后表示該對象參與導航網格的烘培。
- OffMeshLink Generation:勾選后可跳躍(Jump)導航網格和下落(Drop)。
- Navigation Area:可以導航的區域
2. 使用網格導航組件實現跟隨物體位置移動
搭建環境
- 平面障礙物
- 使用Off Mesh Link制作的路徑
- 樓梯
- 斜坡
- 斷層
- 洞口
3. 烘焙導航網格
-
打開導航面板
-
選中要烘焙的地形對象
-
Navigation>>Object>>All,Navigation Static勾選
- Navigation>>Bake
- 調整半徑讓其盡可能多的包含地形對象
- 調整高度(可以進入洞口)
- 調整最大坡度(可以上的坡度)
- 調整臺階高度(可以走上樓梯)
- 調整下落高度(可以從高出落下)
- 調整跳的距離(可以跳過斷層)
- 點擊Bake
-
-
烘焙之后Scene視圖中的效果,所有顯示藍色的網格是可以導航到的位置
-
設置能夠跳躍斷層
- 選中能夠跳躍的對象,Navigation>>Object>>All>>Generate OffMeshLinks勾選,然后進入Bake面點擊Bake
-
烘焙之后Scene視圖中的效果,Plane出現了箭頭指向了另一頭的Plane
- 使用Off Mesh Link制作的路徑
- 創建一個Cube放在第一個Plane的邊緣,克隆一個放在第二個Plane的邊緣
- 在第一個Cube身上添加Off Mesh Link組件,把第一個Cube拖到組件的Start中,把第二個Cube拖到組件的End中,這樣就可以從第一個Plane的第一個Cube的位置到第二個Plane的第二個Cube的位置;中間的黑線就是Off Mesh Link制作的路徑
4. 創建角色和跟隨物體
-
創建一個膠囊體當作小人
-
創建一個Cube當作跟隨物體
5. 在角色身上添加Navigation Mesh Agent組件
6. 腳本
- 功能:讓角色導航到跟隨物體的位置
- 把腳本掛載到角色身上
- 把跟隨物體拖到腳本的實例對象上
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;//人工智能的命名空間
//按下鼠標左鍵玩家跟隨移動
//掛載對象:Player游戲對象
public class Test01 : MonoBehaviour
{
//玩家要到達的位置
public Transform TrCube;
//網格導航代理
private NavMeshAgent mNMA;
void Start()
{
//得到NavMeshAgent組件
mNMA = GetComponent<NavMeshAgent>();
}
void Update()
{
//到指定的位置(終點的位置)
//方法一:通過屬性
mNMA.destination = TrCube.position;
//方法二:通過方法
//mNMA.SetDestination(TrCube.position);
}
}
參考文章:Unity3D 官方文檔 NavMesh三個組件的翻譯與解釋 自動尋路需要知道的細節