[Unity]寻路导航
自動(dòng)尋路
【Unity3D】自動(dòng)尋路系統(tǒng)Navigation實(shí)現(xiàn)人物上樓梯、走斜坡、攀爬、跳躍 - 百度文庫(kù)
?、Navigation?板
這?寫圖?描述
Navigation?板中包括?個(gè)模塊
Agents
這?寫圖?描述
這個(gè)是可以添加多個(gè)NabigationAgents可以?不同的Agents
參數(shù):
Name:設(shè)置烘培Agents的名字
Radius:烘培的半徑,也就是物體的烘培的半徑。這個(gè)值影響物體能通過(guò)的路徑的??
越?,能??的路徑越?,邊緣區(qū)域越?
Height: 具有代表性的物體的?度,可以通過(guò)的最低的空間?度。這個(gè)值越?,能通過(guò)的最??度越?。打個(gè)??就是,1m7的?能通過(guò)
1m7的洞是正常的,你可以設(shè)置height為1m,就能通過(guò)1m的?度
Step Height :梯?的?度,這個(gè)還是要看模型階梯的?度來(lái)設(shè)置
Max Slope:烘培的最?的?度,就是坡度了
Areas
這?寫圖?描述
這個(gè)是可以設(shè)置?動(dòng)尋路烘培的層
配合Nav Mesh Agents使?
這?寫圖?描述
Nav Mesh Agents->Area Mask->可以設(shè)置可以通過(guò)哪些層
Bake
這?寫圖?描述
這個(gè)就是設(shè)置烘培參數(shù)的
參數(shù):
Radius:具有代表性的物體半徑,半徑越??成的?格?積越?。
Height:具有代表性的物體的?度。
Max Slope:斜坡的坡度。
Ste Height:臺(tái)階?度。
Drop Height:允許最?的下落距離。
Jump Distance:允許最?的跳躍距離。
Min Region Area:?格?積?于該值則不?成導(dǎo)航?格。
Height Mesh:勾選后會(huì)保存?度信息,同時(shí)會(huì)消耗?些性能和存儲(chǔ)空間。
Object
這?寫圖?描述
這個(gè)是設(shè)置去烘培哪個(gè)對(duì)象,?如地形之類的,就是可以??的范圍路徑
參數(shù):
Scene Filter:選擇場(chǎng)景中那些對(duì)象,可以選擇全部(All),地形(Terrains),有?格對(duì)象(Mesh Renderers)
Navigation Static:可以烘培
Generate OffMeshLinks:可以跳躍的地?
兩種?成OffMeshLink的?法:
第?種?成OffMeshLink的?法
添加OffMeshLink組件
在這?插?圖?描述
參數(shù):
Start:設(shè)置起點(diǎn)
End:設(shè)置終點(diǎn)
兩者順序沒(méi)有關(guān)系
Cost Override:這個(gè)參數(shù)還沒(méi)有研究
BI Directional:同上
Activated:同上
Auto Update Position:同上
Navigation Area:同上
第?種?成OffMeshLink的?法
在Navigation?板的Object欄??把OffMeshLink Generation選項(xiàng)打上勾
這?寫圖?描述
這?要說(shuō)的?點(diǎn)是,是不是有的?把OffMeshLink Generation選項(xiàng)打上勾之后Back之后還是沒(méi)有出現(xiàn)OffMeshLink
這?寫圖?描述
這是因?yàn)槟銢](méi)有設(shè)置Jump Distance的值
這?寫圖?描述
這個(gè)值越?,能跳的距離越遠(yuǎn),然后能跳的越?
Navigation Area:表?是哪個(gè)Area,這個(gè)需要先設(shè)置,系統(tǒng)默認(rèn)是Walkble、Jump、NotWalkble三種
這個(gè)也要配合Nav Mesh Agent使?
這?寫圖?描述
?、NavMeshAgent組件
2.1 Agent Size
Radius
物體的半徑
Height
物體的?度,如果AgentHeight的值?于這個(gè)值,那么就不能通過(guò)
Base Offset
偏移值
2.2 Steering
Speed
物體?動(dòng)尋路的速度
Angular Speed
轉(zhuǎn)?的速度,就是轉(zhuǎn)彎的速度
Acceleration
加速度
Stopping Distance
物體停下來(lái)的距離,設(shè)置為0就是跟?標(biāo)點(diǎn)的距離為0時(shí)停下來(lái)
Auto Braking
是否?動(dòng)停下來(lái)
2.3 Obstacle Avoidance
Quality
如果要防??群尋路的物體圍住?標(biāo)點(diǎn)
可以設(shè)置Quality為None,即可以讓尋路物體互相穿過(guò)
Priority
優(yōu)先權(quán)
2.4 Path Finding?動(dòng)尋路
Auto Traverse Off Mesh Link
?動(dòng)跳躍鏈接
Auto Repath
?動(dòng)復(fù)制路徑
Area Mask
能通過(guò)的Maks層,這個(gè)可以配合Navigation組件中Areas(設(shè)置層的)使?
三、NavMeshObstacle組件障礙物組件
這?寫圖?描述
如果想要在場(chǎng)景中,動(dòng)態(tài)的放置障礙物,然后也不想在場(chǎng)景開(kāi)始前就洪培好地形的話,就可以在物體上加上這個(gè)組件,然后設(shè)置好參數(shù),將
?動(dòng)尋路組件NavMeshAgent的尋路避讓優(yōu)先級(jí)調(diào)??點(diǎn)
Shape
障礙物的模型,有Box和Capsule兩個(gè)選項(xiàng),從單詞意思就可以看出來(lái)什么意思就不解釋了
Center
中?點(diǎn),如果障礙模型的中?點(diǎn)不在模型的中?點(diǎn)上就可以做?些調(diào)整
Size
設(shè)置??
Carve
Move Threshold 模型 移動(dòng)某個(gè)距離后進(jìn)?烘焙
Time To Stationary 指定模型在某個(gè)位置停??段時(shí)間 后 在進(jìn)?烘焙
Carve One Stationary 勾選后,模型移動(dòng)時(shí)不會(huì)實(shí)時(shí)烘焙
四、實(shí)例例?
步驟?般是這樣的:
1.在場(chǎng)景中擺放各種模型,包括地板,斜坡,?體,扶梯等
2.為所有的模型加上Navigation Static和OffMeshLink Generatic(這個(gè)根據(jù)需要,例如地板與斜坡相連,斜坡就不需要添加
OffMeshLink)
3.特殊處理扶梯,需要?動(dòng)添加Off Mesh Link,設(shè)置好開(kāi)始點(diǎn)和結(jié)束點(diǎn)
4.保存場(chǎng)景,烘焙場(chǎng)景
例??:簡(jiǎn)單尋路
我們要實(shí)現(xiàn)?個(gè)功能:點(diǎn)擊場(chǎng)景中的?個(gè)位置,??可以?動(dòng)尋路過(guò)去。??會(huì)繞過(guò)各種復(fù)雜的障礙,找到?條理論上”最短路徑“。
步驟:
1.創(chuàng)建地形
2.添加??
3.創(chuàng)建多個(gè)障礙物,盡量擺的復(fù)雜?點(diǎn),來(lái)檢查Navmesh的可?性和效率。
4.選中地形,在Navigation窗?中,設(shè)置Navigation Static
5.依次選中障礙物,在avigation窗?中,設(shè)置Navigation Static
7.Navigation窗?中,選擇Bake(烘焙)界?,點(diǎn)擊Bake按鈕,進(jìn)程場(chǎng)景烘焙,就可以烘焙出尋路?格了
8.為??添加NavMeshAgent組件。Component->Navigation->Nav Mesh Agent
9.為??新增?個(gè)腳本PlayerController.cs,實(shí)現(xiàn)點(diǎn)擊?標(biāo),?動(dòng)尋路功能
代碼:
using UnityEngine;
using System.Collections;
public class PlayerController : MonoBehaviour
{
? ? private NavMeshAgent agent;
? ? void Start()
? ? {
? ? ? ? //獲取組件
? ? ? ? agent = GetComponent<NavMeshAgent>();
? ? }
? ? void Update()
? ? {
? ? ? ? //?標(biāo)左鍵點(diǎn)擊
? ? ? ? if (Input.GetMouseButtonDown(0))
? ? ? ? {
? ? ? ? ? ? //攝像機(jī)到點(diǎn)擊位置的的射線
? ? ? ? ? ? Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
? ? ? ? ? ? RaycastHit hit;
? ? ? ? ? ? if (Physics.Raycast(ray, out hit))
? ? ? ? ? ? {
? ? ? ? ? ? ? ? //判斷點(diǎn)擊的是否地形
? ? ? ? ? ? ? ? if (!hit.collider.name.Equals("Terrain"))
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? return;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? //點(diǎn)擊位置坐標(biāo)
? ? ? ? ? ? ? ? Vector3 point = hit.point;
? ? ? ? ? ? ? ? //轉(zhuǎn)向
? ? ? ? ? ? ? ? transform.LookAt(new Vector3(point.x, transform.position.y, point.z));
? ? ? ? ? ? ? ? //設(shè)置尋路的?標(biāo)點(diǎn)
? ? ? ? ? ? ? ? agent.SetDestination(point);
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? //播放動(dòng)畫(huà),判斷是否到達(dá)了?的地,播放空閑或者跑步動(dòng)畫(huà)
? ? ? ? if (agent.remainingDistance == 0)
? ? ? ? {
? ? ? ? ? ? animation.Play("idle");
? ? ? ? }
? ? ? ? else
? ? ? ? {
? ? ? ? ? ? animation.Play("run");
? ? ? ? }
? ? }
}
例??:上下斜坡
烘焙上下斜坡的問(wèn)題
這?寫圖?描述
在?Unity的?動(dòng)尋路系統(tǒng)的時(shí)候,如果?物不能實(shí)現(xiàn)按照規(guī)定到達(dá)?的地,有絕?的原因是烘焙尋路出現(xiàn)了問(wèn)題,所以這是我們?先需要
重視的地?。
下?就是?開(kāi)始我烘焙的尋路,?家可能發(fā)現(xiàn)問(wèn)題了,就是在兩個(gè)紅圈的位置是沒(méi)有烘焙上的,并且區(qū)域很?,當(dāng)?物尋路到這?的時(shí)候很
容易卡在這?。
這?寫圖?描述
那就讓我們來(lái)設(shè)置烘焙的參數(shù)吧。
這?寫圖?描述
?先來(lái)介紹?個(gè)各個(gè)參數(shù)的含義:
Agent Radius:烘焙的半徑,其數(shù)值越?則烘焙效果越好;
Agent Height:烘焙的?度,?物通過(guò)的?度;
Max Slope:烘焙的最?坡度,?于這個(gè)坡度的?將不會(huì)烘焙;
Step Height:烘焙的臺(tái)階?度,如果?度差?于設(shè)置值,將視為連接。
烘焙參數(shù)設(shè)置
所以我們將烘焙半徑調(diào)?點(diǎn)就可以解決這個(gè)問(wèn)題了。
我將烘焙半徑設(shè)置為0.1,烘焙效果如下圖,上坡和下邊的地?連接處沒(méi)有烘焙上的區(qū)域就很?啦。
烘焙好的效果圖
這?寫圖?描述
斜坡?度和連接問(wèn)題
如果上坡的?度很?,?物也會(huì)卡在上坡中,我現(xiàn)在設(shè)置的上坡?度是40度。如果把?度設(shè)置為30度或者以下,?物就可以很順利的爬上
斜坡啦。
上坡?度很?
這?寫圖?描述
如果下坡的?度很?,?物就會(huì)直接跳下斜坡,我現(xiàn)在設(shè)置的下破的?度是50度。可以從圖中看到?物是直接跳下來(lái)的。如果把?度設(shè)置
為40度或者以下,?物就可以很順利的下斜坡啦。
下坡?度很?
這?寫圖?描述
還有就是斜坡與地?和站臺(tái)連接處的問(wèn)題,它們的連接之間?定不能有空隙,否則?物也容易卡在空隙處。如下圖中,斜坡與站臺(tái)沒(méi)有完全
連接上,有個(gè)很?的縫隙,即使尋路也烘焙得沒(méi)有問(wèn)題,?物有時(shí)候也會(huì)卡在這個(gè)地?。
斜坡連接處處理
這?寫圖?描述
?物容易卡在尋路的邊緣處
因?yàn)閷ぢ肪褪墙鉀Q的?物通過(guò)查找最短的路徑(在忽略消耗體?值前提下),并最終達(dá)到?的地的問(wèn)題,所以在上下坡也經(jīng)常會(huì)遇到?物會(huì)
沿著斜坡?邊運(yùn)動(dòng),這個(gè)就可能使?物卡在烘焙好的尋路邊緣處。
我的解決辦法是設(shè)置中間?標(biāo)物,讓其繞開(kāi)尋路邊緣運(yùn)動(dòng),這就需要設(shè)置?個(gè)中間?標(biāo),當(dāng)?物到達(dá)?個(gè)?標(biāo)的時(shí)候,然后向著下?個(gè)?標(biāo)
運(yùn)動(dòng)。
從圖中可以看出設(shè)置了三個(gè)?標(biāo)物,這樣?物就可以順利到達(dá)?標(biāo)3啦。
這?寫圖?描述
代碼:
[RequireComponent(typeof(NavMeshAgent))]
public class NavigationTest : MonoBehaviour {
? ? public Transform targetOne;
? ? public Transform targetTwo;
? ? public Transform targetThree;
? ? private NavMeshAgent navAgent;
? ? private float distanceOne;
? ? private float distanceTwo;
? ? // Use this for initialization
? ? void Start () {
? ? ? ? navAgent = transform.GetComponent<NavMeshAgent>();
? ? ? ? navAgent.SetDestination(targetOne.position);
? ? }
? ? // Update is called once per frame
? ? void Update ()?
? ? {
? ? ? ? CheckReachTarget();
? ? }
? ? void CheckReachTarget()
? ? {
? ? ? ? distanceOne = Vector3.Distance(transform.position,targetOne.position);
? ? ? ? distanceTwo = Vector3.Distance(transform.position,targetTwo.position);
? ? ? ? if (distanceOne < 1f)
? ? ? ? {
? ? ? ? ? ? navAgent.SetDestination(targetTwo.position);
? ? ? ? }
? ? ? ? if (distanceTwo<1f)
? ? ? ? {
? ? ? ? ? ? navAgent.SetDestination(targetThree.position);
? ? ? ? }
? ? }
}
例?三:簡(jiǎn)單的?動(dòng)尋路
1.在Scene中新建三個(gè)Cube,如下圖擺放。
這?寫圖?描述
2.選中上圖三個(gè)Cube,并在Inspector?板中選中為靜態(tài)(static)下拉選項(xiàng)的Navigation Static,如下圖。
這?寫圖?描述
3.依次選擇菜單欄中的Windows - Navigation ,打開(kāi)后?板如下。
這?寫圖?描述
單擊該?板右下?的Bake按鈕,即可?成導(dǎo)航?格,下圖為已?成的導(dǎo)航?格。
在這?插?圖?描述
4.下?就可以讓?個(gè)運(yùn)動(dòng)體根據(jù)?個(gè)導(dǎo)航?格運(yùn)動(dòng)到?標(biāo)位置。
?先新建?個(gè)Cube為?標(biāo)位置,起名TargetCube。然后創(chuàng)建?個(gè)capsule(膠囊)運(yùn)動(dòng)體,為該膠囊掛在?個(gè)Nav Mesh
Agent(Component - Navigation - Nav Mesh Agent);最后寫?個(gè)腳本就可以實(shí)現(xiàn)?動(dòng)尋路了。腳本如下:
using UnityEngine;
using System.Collections;
public class Run : MonoBehaviour {
? ? public Transform TargetObject = null;
? ? void Start () {
? ? ? ? if (TargetObject != null)
? ? ? ? {
? ? ? ? ? ? GetComponent<NavMeshAgent>().destination = TargetObject.position;
? ? ? ? }
? ? }?
? ? void Update () {
? ? }
}
腳本新建完成后掛載到膠囊體上,然后將TargetCube賦予給膠囊體的Run腳本,運(yùn)?場(chǎng)景,如下圖,膠囊體會(huì)按照箭頭的?向運(yùn)動(dòng)到
Cube位置。
這?寫圖?描述
這樣?個(gè)簡(jiǎn)單的?動(dòng)尋路就完成了,如果要更精細(xì)的尋路,或要實(shí)現(xiàn)上坡,鉆"橋洞"等,可根據(jù)下?介紹的相關(guān)參數(shù)進(jìn)?調(diào)節(jié)。
下?介紹Navigation組件和Nav Mesh Agent組件的相關(guān)參數(shù)。
Navigation
Object:物體參數(shù)?板
Navigation Static:勾選后表?該對(duì)象參與導(dǎo)航?格的烘培。
OffMeshLink Generation:勾選后可跳躍(Jump)導(dǎo)航?格和下落(Drop)。
Bake:烘培參數(shù)?板
Radius:具有代表性的物體半徑,半徑越??成的?格?積越?。
Height:具有代表性的物體的?度。
Max Slope:斜坡的坡度。
Ste Height:臺(tái)階?度。
Drop Height:允許最?的下落距離。
Jump Distance:允許最?的跳躍距離。
Min Region Area:?格?積?于該值則不?成導(dǎo)航?格。
Height Mesh:勾選后會(huì)保存?度信息,同時(shí)會(huì)消耗?些性能和存儲(chǔ)空間。
Nav Mesh Agent:導(dǎo)航組建參數(shù)?板
Radius:物體的半徑
Speed:物體的?進(jìn)最?速度
Acceleration:物體的?進(jìn)加速度
Augular Speed:?進(jìn)過(guò)程中轉(zhuǎn)向時(shí)的?速度。
Stopping Distance:離?標(biāo)距離還有多遠(yuǎn)時(shí)停?。
Auto Traverse Off Mesh Link:是否采?默認(rèn)?式度過(guò)鏈接路徑。
Auto Repath:在?進(jìn)某些原因中斷后是否重新開(kāi)始尋路。
Height:物體的?度。
Base Offset:碰撞模型和實(shí)體模型之間的垂直偏移量。
Obstacle Avoidance Type:障礙躲避的的表現(xiàn)登記,None選項(xiàng)為不躲避障礙,另外等級(jí)越?,躲避效果越好,同時(shí)消耗的性能越多。
Avoidance Priority:躲避優(yōu)先級(jí)。
NavMesh Walkable:該物體可以?進(jìn)的?格層掩碼。
例?四:Navigation實(shí)現(xiàn)?低落差以及跳躍的做法
在這?插?圖?描述
在這?插?圖?描述
不管是爬樓梯,還是跳躍,NavMesh都是通過(guò)了OffMeshLink來(lái)做的。創(chuàng)建OffMeshLink的?法有兩種,接下來(lái)會(huì)通過(guò)制作上?的例?
來(lái)進(jìn)?說(shuō)明:
這?寫圖?描述
為了做這個(gè)例?,我們預(yù)先在場(chǎng)景??準(zhǔn)備了?些物體:攝像機(jī)是必須的,?個(gè)作為地?的Plane,然后是F1——F5?個(gè)?低落差不?樣
的臺(tái)階,L1和L2是樓梯模型, 控制?物主體man,還有移動(dòng)的?標(biāo)點(diǎn)target。
其中man?上必須帶有NavMesh Agent組件,為了觀察?便在target?上帶了light組件。
這?寫圖?描述
按照上?節(jié)所講的,plane和F1——F5臺(tái)階在Navigation?板勾選Navigation Static選項(xiàng),然后Bake,觀察Scene視窗,會(huì)發(fā)現(xiàn)已經(jīng)?成
了我們所要的NavMesh?格,現(xiàn)在我們可以像上?節(jié)那樣在plane上?給?物做尋路和移動(dòng)了,但?物是不會(huì)爬樓梯的。
這時(shí)候,我們找到L1樓梯,在樓梯的開(kāi)始和結(jié)束的位置放置兩個(gè)點(diǎn),這兩個(gè)點(diǎn)只需要拾取它的位移的,你可以?empty Gameobject來(lái)
做,我這?為了便于觀察,就拿了cube來(lái)做。開(kāi)始點(diǎn)命名為startPoint,結(jié)束點(diǎn)命名為endPoint。
這?寫圖?描述
注意:startPoint和endPoint的位置要稍微?所在的平???點(diǎn)點(diǎn)。
接下來(lái)介紹第?種?成OffMeshLink的?法。選擇L1樓梯,然后在Component下拉選項(xiàng)中選擇Navigation——Off Mesh Link。
這?寫圖?描述
選擇后,OffMeshLink組件已經(jīng)添加到了L1的?上,我們可以在Inspector?板看到:
我們把剛才放置在場(chǎng)景??的startPoint和endPoint指定到OffmeshLink組件的Start和End位置,其他選項(xiàng)默認(rèn)不改變
這?寫圖?描述
再次Bake
這?寫圖?描述
這?寫圖?描述
現(xiàn)在我們發(fā)現(xiàn),在scene?板??,在startPoint和endPoint之間?成了?條線,??向是從startPoint指向endPoint的。
在這?插?圖?描述
這時(shí)候,你應(yīng)該可以通過(guò)移動(dòng)?標(biāo)點(diǎn)讓??開(kāi)始爬樓梯了。但爬上去之后??暫時(shí)不能跳下來(lái),如果把?標(biāo)點(diǎn)移動(dòng)到plane上,??會(huì)順著
樓梯爬下來(lái)。
我們使?同樣的?法對(duì)L2進(jìn)??成OffMeshLink。這時(shí)候,??應(yīng)該可以爬兩層樓梯了。到此第?個(gè)?標(biāo)完成了。
接下來(lái)我們進(jìn)?第?個(gè)?標(biāo)的制作,?先先來(lái)分析?下我們的場(chǎng)景:
這?寫圖?描述
我們希望?物能從2.5M的?度往下跳,超過(guò)2.5M?物就不能跳了,太?會(huì)有危險(xiǎn)。然后橫向我們希望?物能跳過(guò)2?的溝。
根據(jù)這個(gè)設(shè)定,我們的場(chǎng)景會(huì)是這樣的情況:L1和L2只能通過(guò)爬樓梯,L2和L3之間可以跳躍,L3——L5是可以往下跳的。
于是,我們?cè)贜avigation?板??找到Bake欄,Drop Height(掉落?度)填2.5,Jump Distance(跳躍距離)填2,單位都是?
這?寫圖?描述
接下來(lái)介紹第?種?成OffMeshLink的?法:
我們把L1——L5的物體選中,在Navigation?板的Object欄??把OffMeshLink Generation選項(xiàng)打上勾
這?寫圖?描述
再次Bake,回到scene視窗:
這?寫圖?描述
這時(shí)候,場(chǎng)景??會(huì)出現(xiàn)很多?的OffMeshLink,這是unity通過(guò)計(jì)算,把可以跳躍或者下落的地??動(dòng)?成了OffMeshLink了。
這時(shí)候,你應(yīng)該已經(jīng)可以通過(guò)移動(dòng)?標(biāo)點(diǎn),讓??進(jìn)?跳躍和下落了。
進(jìn)?到這?,我們的第?個(gè)?標(biāo)也完成了。
不過(guò)有些朋友可能會(huì)提出疑問(wèn),在做的過(guò)程中,假如沒(méi)有這個(gè)?兵的模型,?是??個(gè)膠囊體來(lái)代替?物的話,它爬樓梯和跳躍的時(shí)候好像
是在?瞬間完成的,沒(méi)有?兵那個(gè)爬樓梯和跳躍動(dòng)作的過(guò)程。如這樣:
這?寫圖?描述
這?寫圖?描述
的確是這樣,因?yàn)槟J(rèn)的NaveMesh Agent組件上?是勾選了Auto Traverse Off Mesh Link(?動(dòng)通過(guò)OffMeshLink)選項(xiàng)的。這樣的
意思是?物只要到了OffMeshLink的開(kāi)始點(diǎn),就會(huì)?動(dòng)的移動(dòng)到OffMeshLink的結(jié)束點(diǎn)。
這?寫圖?描述
假如各位需要對(duì)越過(guò)OffMeshLink時(shí)候進(jìn)???的控制,是需要另外寫腳本的。我這?簡(jiǎn)單的介紹?下?法,有興趣的朋友可以??試
試。
?先各位最好有?狀態(tài)來(lái)控制??的概念。?如?物可以分為站?、?路、跑步、上下樓梯、橫向跳躍和往下掉落?種狀態(tài),針對(duì)
NavMesh來(lái)說(shuō),?物簡(jiǎn)單的可以分為站?、正常的NavMesh尋路,和通過(guò)OffMeshLink移動(dòng)?種狀態(tài)。
先把 Auto Traverse Off Mesh Link選項(xiàng)取消。
然后,當(dāng)?物在通過(guò)OffMeshLink移動(dòng)的狀態(tài)(可以?NavMeshAgent.isOnOffMeshLink來(lái)判斷),獲取到當(dāng)前通過(guò)的
OffMeshLink:
OffMeshLinkData link = NavMeshAgent.currentOffMeshLinkData;
這樣你就能獲取到link的開(kāi)始點(diǎn)和結(jié)束點(diǎn)的坐標(biāo)(link.startPos和link.endPos),這時(shí)候你的?物就可以?最簡(jiǎn)單的Vector3.Lerp來(lái)進(jìn)?
移動(dòng),當(dāng)?物的位移到達(dá)了結(jié)束點(diǎn)的坐標(biāo),?物的OffMeshLink移動(dòng)狀態(tài)就可以結(jié)束,?重新變回正常尋路或者站?的狀態(tài)了。在這個(gè)
Vector3.Lerp的過(guò)程中,你可以隨意的控制?物的爬?或者跳躍的動(dòng)作。
例?五:?動(dòng)尋路Navmesh之跳躍,攀爬,斜坡
步驟:
1.在場(chǎng)景中擺放各種模型,包括地板,斜坡,?體,扶梯等
2.為所有的模型加上Navigation Static和OffMeshLink Generatic(這個(gè)根據(jù)需要,例如地板與斜坡相連,斜坡就不需要添加
OffMeshLink)
3.特殊處理扶梯,需要?動(dòng)添加Off Mesh Link,設(shè)置好開(kāi)始點(diǎn)和結(jié)束點(diǎn)
4.保存場(chǎng)景,烘焙場(chǎng)景
5.添加??模型,為其加Nav Mesh Agent組件
6.為??添加?個(gè)新腳本,AgentLocomotion.cs,?來(lái)處理?動(dòng)尋路,已經(jīng)??動(dòng)畫(huà)變換。代碼?較長(zhǎng),?家可以結(jié)合注釋來(lái)理解
代碼:
using UnityEngine; ?
using System.Collections; ?
public class AgentLocomotion : MonoBehaviour ?
{ ?
? ? private Vector3 target;//?標(biāo)位置
? ? private NavMeshAgent agent; ?
? ? private Animation anim;//動(dòng)畫(huà)
? ? private string locoState = "Locomotion_Stand"; ?
? ? private Vector3 linkStart;//OffMeshLink的開(kāi)始點(diǎn)
? ? private Vector3 linkEnd;//OffMeshLink的結(jié)束點(diǎn)
? ? private Quaternion linkRotate;//OffMeshLink的旋轉(zhuǎn)
? ? private bool begin;//是否開(kāi)始尋路
? ? // Use this for initialization ?
? ? void Start() ?
? ? { ?
? ? ? ? agent = GetComponent<NavMeshAgent>(); ?
? ? ? ? //?動(dòng)移動(dòng)并關(guān)閉OffMeshLinks,即在兩個(gè)隔離障礙物直接?成的OffMeshLink,agent不會(huì)?動(dòng)越過(guò)
? ? ? ? agent.autoTraverseOffMeshLink = false; ?
? ? ? ? //創(chuàng)建動(dòng)畫(huà)
? ? ? ? AnimationSetup(); ?
? ? ? ? //起?個(gè)協(xié)程,處理動(dòng)畫(huà)狀態(tài)機(jī)
? ? ? ? StartCoroutine(AnimationStateMachine()); ?
? ? } ?
? ? void Update() ?
? ? { ?
? ? ? ? //?標(biāo)左鍵點(diǎn)擊
? ? ? ? if (Input.GetMouseButtonDown(0)) ?
? ? ? ? { ?
? ? ? ? ? ? //攝像機(jī)到點(diǎn)擊位置的的射線
? ? ? ? ? ? Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); ?
? ? ? ? ? ? RaycastHit hit; ?
? ? ? ? ? ? if (Physics.Raycast(ray, out hit)) ?
? ? ? ? ? ? { ?
? ? ? ? ? ? ? ? //判斷點(diǎn)擊的是否地形
? ? ? ? ? ? ? ? if (hit.collider.tag.Equals("Obstacle")) ?
? ? ? ? ? ? ? ? { ?
? ? ? ? ? ? ? ? ? ? begin = true; ?
? ? ? ? ? ? ? ? ? ? //點(diǎn)擊位置坐標(biāo)
? ? ? ? ? ? ? ? ? ? target = hit.point; ?
? ? ? ? ? ? ? ? } ?
? ? ? ? ? ? } ?
? ? ? ? } ?
? ? ? ? //每?幀,設(shè)置?標(biāo)點(diǎn)
? ? ? ? if (begin) ?
? ? ? ? if (begin) ?
? ? ? ? { ?
? ? ? ? ? ? agent.SetDestination(target); ?
? ? ? ? } ?
? ? } ?
? ? IEnumerator AnimationStateMachine() ?
? ? { ?
? ? ? ? //根據(jù)locoState不同的狀態(tài)來(lái)處理,調(diào)?相關(guān)的函數(shù)
? ? ? ? while (Application.isPlaying) ?
? ? ? ? { ?
? ? ? ? ? ? yield return StartCoroutine(locoState); ?
? ? ? ? } ?
? ? } ?
? ? //站?
? ? IEnumerator Locomotion_Stand() ?
? ? { ?
? ? ? ? do ?
? ? ? ? { ?
? ? ? ? ? ? UpdateAnimationBlend(); ?
? ? ? ? ? ? yield return new WaitForSeconds(0); ?
? ? ? ? } while (agent.remainingDistance == 0); ?
? ? ? ? //未到達(dá)?標(biāo)點(diǎn),轉(zhuǎn)到下?個(gè)狀態(tài)Locomotion_Move ?
? ? ? ? locoState = "Locomotion_Move"; ?
? ? ? ? yield return null; ?
? ? } ?
? ? IEnumerator Locomotion_Move() ?
? ? { ?
? ? ? ? do ?
? ? ? ? { ?
? ? ? ? ? ? UpdateAnimationBlend(); ?
? ? ? ? ? ? yield return new WaitForSeconds(0); ?
? ? ? ? ? ? //??處于OffMeshLink,根據(jù)不同的地點(diǎn),選擇不同動(dòng)畫(huà)
? ? ? ? ? ? if (agent.isOnOffMeshLink) ?
? ? ? ? ? ? { ?
? ? ? ? ? ? ? ? locoState = SelectLinkAnimation(); ?
? ? ? ? ? ? ? ? return (true); ?
? ? ? ? ? ? } ?
? ? ? ? } while (agent.remainingDistance != 0); ?
? ? ? ? //已經(jīng)到達(dá)?標(biāo)點(diǎn),狀態(tài)轉(zhuǎn)為Stand ?
? ? ? ? locoState = "Locomotion_Stand"; ?
? ? ? ? yield return null; ?
? ? } ?
? ? IEnumerator Locomotion_Jump() ?
? ? { ?
? ? ? ? //播放跳躍動(dòng)畫(huà)
? ? ? ? string linkAnim = "RunJump"; ?
? ? ? ? Vector3 posStart = transform.position; ?
? ? ? ? agent.Stop(true); ?
? ? ? ? anim.CrossFade(linkAnim, 0.1f, PlayMode.StopAll); ?
? ? ? ? transform.rotation = linkRotate; ?
? ? ? ? do ?
? ? ? ? { ?
? ? ? ? ? ? //計(jì)算新的位置
? ? ? ? ? ? float tlerp = anim[linkAnim].normalizedTime; ?
? ? ? ? ? ? Vector3 newPos = Vector3.Lerp(posStart, linkEnd, tlerp); ?
? ? ? ? ? ? newPos.y += 0.4f * Mathf.Sin(3.14159f * tlerp); ?
? ? ? ? ? ? transform.position = newPos; ?
? ? ? ? ? ? yield return new WaitForSeconds(0); ?
? ? ? ? } while (anim[linkAnim].normalizedTime < 1); ?
? ? ? ? } while (anim[linkAnim].normalizedTime < 1); ?
? ? ? ? //動(dòng)畫(huà)恢復(fù)到Idle ?
? ? ? ? anim.Play("Idle"); ?
? ? ? ? agent.CompleteOffMeshLink(); ?
? ? ? ? agent.Resume(); ?
? ? ? ? //下?個(gè)狀態(tài)為Stand ?
? ? ? ? transform.position = linkEnd; ?
? ? ? ? locoState = "Locomotion_Stand"; ?
? ? ? ? yield return null; ?
? ? } ?
? ? //梯?
? ? IEnumerator Locomotion_Ladder() ?
? ? { ?
? ? ? ? //梯?的中?位置
? ? ? ? Vector3 linkCenter = (linkStart + linkEnd) * 0.5f; ?
? ? ? ? string linkAnim; ?
? ? ? ? //判斷是在梯?上還是梯?下
? ? ? ? if (transform.position.y > linkCenter.y) ?
? ? ? ? ? ? linkAnim = "Ladder Down"; ?
? ? ? ? else ?
? ? ? ? ? ? linkAnim = "Ladder Up"; ?
? ? ? ? agent.Stop(true); ?
? ? ? ? Quaternion startRot = transform.rotation; ?
? ? ? ? Vector3 startPos = transform.position; ?
? ? ? ? float blendTime = 0.2f; ?
? ? ? ? float tblend = 0f; ?
? ? ? ? //??的位置插值變化(0.2內(nèi)變化)
? ? ? ? do ?
? ? ? ? { ?
? ? ? ? ? ? transform.position = Vector3.Lerp(startPos, linkStart, tblend / blendTime); ?
? ? ? ? ? ? transform.rotation = Quaternion.Lerp(startRot, linkRotate, tblend / blendTime); ?
? ? ? ? ? ? yield return new WaitForSeconds(0); ?
? ? ? ? ? ? tblend += Time.deltaTime; ?
? ? ? ? } while (tblend < blendTime); ?
? ? ? ? //設(shè)置位置
? ? ? ? transform.position = linkStart; ?
? ? ? ? //播放動(dòng)畫(huà)
? ? ? ? anim.CrossFade(linkAnim, 0.1f, PlayMode.StopAll); ?
? ? ? ? agent.ActivateCurrentOffMeshLink(false); ?
? ? ? ? //等待動(dòng)畫(huà)結(jié)束
? ? ? ? do ?
? ? ? ? { ?
? ? ? ? ? ? yield return new WaitForSeconds(0); ?
? ? ? ? } while (anim[linkAnim].normalizedTime < 1); ?
? ? ? ? agent.ActivateCurrentOffMeshLink(true); ?
? ? ? ? //恢復(fù)Idle狀態(tài)
? ? ? ? anim.Play("Idle"); ?
? ? ? ? transform.position = linkEnd; ?
? ? ? ? agent.CompleteOffMeshLink(); ?
? ? ? ? agent.Resume(); ?
? ? ? ? //下?個(gè)狀態(tài)Stand ?
? ? ? ? locoState = "Locomotion_Stand"; ?
? ? ? ? yield return null; ?
? ? } ?
? ? private string SelectLinkAnimation() ?
? ? { ?
? ? ? ? //獲得當(dāng)前的OffMeshLink數(shù)據(jù)
? ? ? ? OffMeshLinkData link = agent.currentOffMeshLinkData; ?
? ? ? ? //計(jì)算??當(dāng)前是在link的開(kāi)始點(diǎn)還是結(jié)束點(diǎn)(因?yàn)镺ffMeshLink是雙向的)
? ? ? ? float distS = (transform.position - link.startPos).magnitude; ?
? ? ? ? float distE = (transform.position - link.endPos).magnitude; ?
? ? ? ? float distE = (transform.position - link.endPos).magnitude; ?
? ? ? ? if (distS < distE) ?
? ? ? ? { ?
? ? ? ? ? ? linkStart = link.startPos; ?
? ? ? ? ? ? linkEnd = link.endPos; ?
? ? ? ? } ?
? ? ? ? else ?
? ? ? ? { ?
? ? ? ? ? ? linkStart = link.endPos; ?
? ? ? ? ? ? linkEnd = link.startPos; ?
? ? ? ? } ?
? ? ? ? //OffMeshLink的?向
? ? ? ? Vector3 alignDir = linkEnd - linkStart; ?
? ? ? ? //忽略y軸
? ? ? ? alignDir.y = 0; ?
? ? ? ? //計(jì)算旋轉(zhuǎn)?度
? ? ? ? linkRotate = Quaternion.LookRotation(alignDir); ?
? ? ? ? //判斷OffMeshLink是?動(dòng)的(樓梯)還是?動(dòng)?成的(跳躍)
? ? ? ? if (link.linkType == OffMeshLinkType.LinkTypeManual) ?
? ? ? ? { ?
? ? ? ? ? ? return ("Locomotion_Ladder"); ?
? ? ? ? } ?
? ? ? ? else ?
? ? ? ? { ?
? ? ? ? ? ? return ("Locomotion_Jump"); ?
? ? ? ? } ?
? ? } ?
? ? private void AnimationSetup() ?
? ? { ?
? ? ? ? anim = GetComponent<Animation>(); ?
? ? ? ? // 把walk和run動(dòng)畫(huà)放到同?層,然后同步他們的速度。
? ? ? ? anim["Walk"].layer = 1; ?
? ? ? ? anim["Run"].layer = 1; ?
? ? ? ? anim.SyncLayer(1); ?
? ? ? ? //設(shè)置“跳躍”,“爬樓梯”,“下樓梯”的動(dòng)畫(huà)模式和速度
? ? ? ? anim["RunJump"].wrapMode = WrapMode.ClampForever; ?
? ? ? ? anim["RunJump"].speed = 2; ?
? ? ? ? anim["Ladder Up"].wrapMode = WrapMode.ClampForever; ?
? ? ? ? anim["Ladder Up"].speed = 2; ?
? ? ? ? anim["Ladder Down"].wrapMode = WrapMode.ClampForever; ?
? ? ? ? anim["Ladder Down"].speed = 2; ?
? ? ? ? //初始化動(dòng)畫(huà)狀態(tài)為Idle ?
? ? ? ? anim.CrossFade("Idle", 0.1f, PlayMode.StopAll); ?
? ? } ?
? ? //更新動(dòng)畫(huà)融合
? ? private void UpdateAnimationBlend() ?
? ? { ?
? ? ? ? //??速度
? ? ? ? float walkAnimationSpeed = 1.5f; ?
? ? ? ? //奔跑速度
? ? ? ? float runAnimationSpeed = 4.0f; ?
? ? ? ? //速度閥值(idle和walk的臨界點(diǎn))
? ? ? ? float speedThreshold = 0.1f; ?
? ? ? ? //速度,只考慮x和z ?
? ? ? ? Vector3 velocityXZ = new Vector3(agent.velocity.x, 0.0f, agent.velocity.z); ?
? ? ? ? //速度值
? ? ? ? float speed = velocityXZ.magnitude; ?
? ? ? ? //設(shè)置Run動(dòng)畫(huà)的速度
? ? ? ? anim["Run"].speed = speed / runAnimationSpeed; ?
? ? ? ? anim["Run"].speed = speed / runAnimationSpeed; ?
? ? ? ? //設(shè)置Walk動(dòng)畫(huà)的速度
? ? ? ? anim["Walk"].speed = speed / walkAnimationSpeed; ?
? ? ? ? //根據(jù)agent的速度??,確定animation的播放狀態(tài)
? ? ? ? if (speed > (walkAnimationSpeed + runAnimationSpeed) / 2) ?
? ? ? ? { ?
? ? ? ? ? ? anim.CrossFade("Run"); ?
? ? ? ? } ?
? ? ? ? else if (speed > speedThreshold) ?
? ? ? ? { ?
? ? ? ? ? ? anim.CrossFade("Walk"); ?
? ? ? ? } ?
? ? ? ? else ?
? ? ? ? { ?
? ? ? ? ? ? anim.CrossFade("Idle", 0.1f, PlayMode.StopAll); ?
? ? ? ? } ?
? ? } ?
} ?
效果圖:
點(diǎn)擊任何?個(gè)地點(diǎn),??都可以?動(dòng)尋路過(guò)去。中間可能經(jīng)過(guò)不同的障礙物,我們可以看到??如我們所預(yù)料的?樣,可以跳躍下來(lái),可以
爬樓梯,最終到達(dá)?標(biāo)點(diǎn)。
這?寫圖?描述
源碼:
例?六:?動(dòng)尋路Navmesh之?級(jí)主題
隔離層?動(dòng)?成尋路?格
1.創(chuàng)建Plane實(shí)例P1,P2,兩者之間出現(xiàn)?條鴻溝。直接控制??位移是?法通過(guò)的。
2.打開(kāi)Navigation窗?,分別選中P1,P2,分別設(shè)置Navigation Static 和OffMeshLink Generatic
這?寫圖?描述
3.保存場(chǎng)景,點(diǎn)擊場(chǎng)景烘焙按鈕Bake。結(jié)束后我們可以看到P1,P2除了???產(chǎn)尋路?格外,它們直接還?成了連接紐帶。
4.添加??模型Solder,為其添加NavMeshAgent(Component->Navigation->NavMeshAgent)
5.給Solder添加PlayerController腳本
代碼:
using UnityEngine; ?
using System.Collections; ?
public class PlayerController : MonoBehaviour ?
{ ?
? ? private NavMeshAgent agent; ?
? ? public bool setAgentWalkMask;//是否需要?jiǎng)討B(tài)修改尋路層,在scene4的實(shí)例中要?到
? ? void Start() ?
? ? { ?
? ? ? ? //獲取尋路組件
? ? ? ? agent = GetComponent<NavMeshAgent>(); ?
? ? } ?
? ? void Update() ?
? ? { ?
? ? ? ? //?標(biāo)左鍵點(diǎn)擊
? ? ? ? if (Input.GetMouseButtonDown(0)) ?
? ? ? ? { ?
? ? ? ? ? ? //攝像機(jī)到點(diǎn)擊位置的的射線
? ? ? ? ? ? Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); ?
? ? ? ? ? ? RaycastHit hit; ?
? ? ? ? ? ? if (Physics.Raycast(ray, out hit)) ?
? ? ? ? ? ? { ?
? ? ? ? ? ? ? ? //判斷點(diǎn)擊的是否地形
? ? ? ? ? ? ? ? if (!hit.collider.tag.Equals("Plane")) ?
? ? ? ? ? ? ? ? { ?
? ? ? ? ? ? ? ? ? ? return; ?
? ? ? ? ? ? ? ? } ?
? ? ? ? ? ? ? ? //點(diǎn)擊位置坐標(biāo)
? ? ? ? ? ? ? ? Vector3 point = hit.point; ?
? ? ? ? ? ? ? ? //轉(zhuǎn)向
? ? ? ? ? ? ? ? transform.LookAt(new Vector3(point.x, transform.position.y, point.z)); ?
? ? ? ? ? ? ? ? //設(shè)置尋路的?標(biāo)點(diǎn)
? ? ? ? ? ? ? ? agent.SetDestination(point); ?
? ? ? ? ? ? } ?
? ? ? ? } ?
? ? ? ? //播放動(dòng)畫(huà)
? ? ? ? if (agent.remainingDistance == 0) ?
? ? ? ? { ?
? ? ? ? ? ? animation.Play("Idle"); ?
? ? ? ? } ?
? ? ? ? else ?
? ? ? ? { ?
? ? ? ? ? ? animation.Play("Run"); ?
? ? ? ? } ?
? ? } ?
} ?
5.點(diǎn)擊任意的位置,可以看到??都能?動(dòng)尋路過(guò)去
效果圖
這?寫圖?描述
?動(dòng)指定尋路?格?向
1.將P1,P2的OffMeshLink Generatic去除
2.在P1上新建?個(gè)空的GameObject Start,P2上新建?個(gè)空的GameObject End
3.選中start,為它添加Off Mesh Link組件 Component->Navigation->OffMeshLink
4.設(shè)置Off Mesh Link組件的屬性,Start Point 為 start,End Point為end
5.烘焙場(chǎng)景。我們可以看到有?條紐帶從start指向end
點(diǎn)擊地圖,可以看到??如果要跨越P1和P2,?定是沿著我們?動(dòng)創(chuàng)建的路徑
這?寫圖?描述
導(dǎo)航?格障礙物 Navmesh Obstacle
之前我們都是?固定的物體作為障礙物,然后烘焙場(chǎng)景。Unity還提供了動(dòng)態(tài)的障礙物。任何?個(gè)GameObject都可以添加Navmesh
Obstacle組件,變成?個(gè)障礙物。具體步驟是Component->Navigation->Navmesh Obstacle.它有兩個(gè)屬性:半徑和?度,可以設(shè)置跟
你的物品差不多的體積??。
尋路?格層的應(yīng)?
1.新建P1,P2,P3,P4等4個(gè)Plane,具體擺設(shè)形狀見(jiàn)效果圖
2.在Navigation窗?中,添加兩個(gè)層Layers:Blue層和Red層
3.P1,P2的Navigation Layer設(shè)置為Default,P4的Navigation層設(shè)置為Red,P3設(shè)置為Blue
4.添加兩個(gè)??,設(shè)置他們的NavMeshAgent尋路層(NavMesh Walkable)。?個(gè)將Red層去掉,?個(gè)將Blue層去掉
5.點(diǎn)擊P2的坐標(biāo),可以看到他們沿著不同的路徑去?標(biāo)點(diǎn),?個(gè)?上層路線,?個(gè)?下層路線了。
效果圖
這?寫圖?描述
動(dòng)態(tài)改變尋路?格層
1.在scene3.unity基礎(chǔ)上做?下修改。只保留?個(gè)??
2.新增兩個(gè)按鈕,“?上層”和“?下層”,在游戲運(yùn)?時(shí),可以改變Agent的尋路層。
代碼:
//動(dòng)態(tài)設(shè)置尋路路徑層
?void OnGUI() ?
? ?{ ?
? ? ? ?if (!setAgentWalkMask) ?
? ? ? ?{ ?
? ? ? ? ? ?return; ?
? ? ? ?} ?
? ? ? ?if (GUI.Button(new Rect(0, 0, 100, 50), "?下層")) ?
? ? ? ?{ ?
? ? ? ? ? ?agent.walkableMask = 65; ?
? ? ? ?} ?
? ? ? ?if (GUI.Button(new Rect(0, 100, 100, 50), "?上層")) ?
? ? ? ?{ ?
? ? ? ? ? ?agent.walkableMask = 129; ?
? ? ? ?} ?
? ?} ?
3.重新點(diǎn)擊尋路,可以看到,選擇不同的尋路層,??的尋路路徑也不同
這?寫圖?描述
看到代碼中的agent.walkableMask = 65和129,?家會(huì)?較迷惑,其實(shí)尋路層每?層都是2的冪,見(jiàn)下圖
這?寫圖?描述
所以上層的mask = Default(1)+Blue(128) = 129,下層的mak = Default(1)+Red(64) = 65
例?七:Navigation烘焙
Building a NavMesh
在Unity中,NavMesh 的?成操作需要Navigation窗?(在Window> Navigation)
在你的場(chǎng)景中構(gòu)建NavMesh只需要4個(gè)步驟:
這?寫圖?描述
在這?插?圖?描述
選擇場(chǎng)景中需要?成尋路的?何體-可??表?和障礙物。
在NavMesh?板中選擇需要烘焙尋路的物體,檢測(cè)是否勾選Navigation Static.
根據(jù)你的agent??來(lái)調(diào)整bake ?板的設(shè)置。
Agent Radius : agent可以距離墻體 ,窗戶或邊緣多近的距離。
Agent Height : agent可以通過(guò)的最低的空間?度。
Max Slope : agent可以直接??上去的最?坡度。
Step Height: agent可以踩上(?上)的障礙物最??度。
點(diǎn)擊bake按鈕烘焙NavMesh。
當(dāng)你的Navigation窗?打開(kāi)并且可見(jiàn)時(shí),烘焙的NavMesh結(jié)果在場(chǎng)景中會(huì)以藍(lán)?的覆蓋層在物體的?何體表?顯?。
這?寫圖?描述
烘焙完成后,您將在與NavMesh所屬場(chǎng)景同名的?件夾中找到?個(gè)NavMesh資產(chǎn)?件。例如,如果在Assets?件夾中有?個(gè)名為First
Level的場(chǎng)景,NavMesh將位于 Assets > First Level > NavMesh.asset.當(dāng)烘焙結(jié)束后,你可以找到?個(gè)名字和你的場(chǎng)景名?樣的?件
夾,??有?個(gè)NavMesh的資源?件,是屬于這個(gè)場(chǎng)景的NavMesh。
讓物體可烘焙的其他?法
這?寫圖?描述
直接選擇物體在Inspector?板頂部的Static 菜單,你可以直接選擇Navigation Static,?不?再打開(kāi)Navigation 窗?。
NavMesh烘焙的?級(jí)設(shè)置
最?區(qū)域?積
這?寫圖?描述
這?寫圖?描述
Min Region Area 允許你剔除掉?的?連接NavMesh區(qū)域,當(dāng)NavMesh區(qū)域?于指定值時(shí)將被剔除。
請(qǐng)注意:有些區(qū)域可能?法被移除,盡管有Min Region Area 的設(shè)置,原因是NavMesh的構(gòu)建是?個(gè)個(gè)的?格并?構(gòu)建。當(dāng)?個(gè)區(qū)域橫跨
兩個(gè)?格將不會(huì)被移除,因?yàn)閰^(qū)域修剪過(guò)程中?法獲取到周圍的?格。
Voxel Size ?體像素尺?
Manual voxel size :允許你改變烘焙操作過(guò)程中的精確性。
Navigation在構(gòu)建尋路?格過(guò)程中,第?遍會(huì)把場(chǎng)景光柵化為體素,然后提取可??區(qū)域,最后可??區(qū)域會(huì)烘焙成?格。因此體素尺?
Voxel Size的決定了尋路?格烘焙的精準(zhǔn)性。
提?:默認(rèn)的體素設(shè)置最好的權(quán)衡了準(zhǔn)確性和烘焙速度。在烘焙場(chǎng)景尋路的過(guò)程中,體素的增加會(huì)造成4x倍的內(nèi)存消耗和4x倍的時(shí)間消
耗。因此通常,你不需要??去設(shè)置Voxel Size。
這?寫圖?描述
Smaller Agent Radius
系統(tǒng)烘焙尋路是也會(huì)減?voxel size。如果你的agent尺?保持不變,可能不需要增加NavMesh的構(gòu)建分辨率。
更簡(jiǎn)單的?法如下所?:
設(shè)置你的半徑為真實(shí)agent半徑
打開(kāi)Manual Voxel Size,這會(huì)保持當(dāng)前的voxel的??并且凍結(jié)它。
?為的將你的Agent Radius設(shè)置?,因?yàn)槟阋呀?jīng)勾選了Manual Voxel Size ,voxel size將不會(huì)改變。
Height mesh : 允許你為??提供更精準(zhǔn)的位置。
這?寫圖?描述
導(dǎo)航時(shí),NavMesh代理被約束在NavMesh的表?。由于NavMesh是可步?空間的近似,所以在構(gòu)建NavMesh時(shí),?些特性會(huì)被平均化。
例如,樓梯可能在NavMesh中顯?為?個(gè)斜坡。如果你的游戲需要準(zhǔn)確的位置代理,你應(yīng)該啟??度?格建設(shè)時(shí),你烤NavMesh。該設(shè)置
可以在導(dǎo)航窗?的?級(jí)設(shè)置中找到。注意,建筑?度?格將占?內(nèi)存和處理在運(yùn)?時(shí),它將需要更長(zhǎng)的時(shí)間來(lái)烘烤NavMesh。
盡管普通的NavMesh 已經(jīng)可以很好的運(yùn)?,但是由于NavMesh只是?個(gè)近似的可??的空間,只保持了?些均衡的特性,如果你的游戲
agent需要更精準(zhǔn)的??位置,你可以啟??度?格Height Mesh,
注意:?度?格Height Mesh將占?你“運(yùn)?時(shí)”的內(nèi)存和cpu,并且需要更多的烘焙時(shí)間。
結(jié)束。。。
這篇?章吸取了很多?的精華,有什么不對(duì)的地?希望都可以私信我。
?
總結(jié)
以上是生活随笔為你收集整理的[Unity]寻路导航的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 定制Github日历库EPCalenda
- 下一篇: FOC电机ST系列处理器使用的基础知识