unity自從3.5版本之后,增加了NavMesh尋路的功能鞋拟。在此之前盘寡,unity用戶只能通過第三方插件(如Astar尋路插件)等做尋路功能。我也使用過A*尋路插件侠畔,A*的原理并不復雜结缚,有興趣的朋友可以自己百度一下。不過由于不是自帶的功能软棺,所以在設(shè)定網(wǎng)格和烘焙的過程難免會出現(xiàn)很多不便红竭。NavMesh作為unity自帶的功能,用法和之前的LightMapping烘焙或者遮擋剔除Occlusion Culling有很多相似之處喘落。
先來看看怎么在unity打開NavMesh功能的窗口吧:
在window下拉列表中可以看到Navgation茵宪,點擊:
在原來Inspector面板的旁邊會出現(xiàn)Navigation的面板:
這個Objcet的面板是對應(yīng)當前選擇的物體的,旁邊的Bake面板是對應(yīng)全局選項的瘦棋。結(jié)構(gòu)和烘焙或者遮擋剔除是一樣的稀火。在選擇了物體的情況下會出現(xiàn)上面的內(nèi)容:
上面的All、MeshRenderers赌朋、Terranis是對Hirarchy面板里面顯示的物品選擇的一個篩選過濾:
all就是全部顯示
MeshRenderers是只顯示可渲染的網(wǎng)格物體
而Terrains當然就是只顯示地形物體了凰狞。
下面的是重要的選項,第一個Navigation Static選項是選擇該物體是否用做尋路功能的一部分沛慢。只有勾選了這個選項赡若,下面的其他選項才會可操作。
OffMeshLink Generation選項是選擇該物體是否根據(jù)高度团甲、可跳躍寬帶等全局的選項自動生成OffMeshLink逾冬,這個會在以后的講解中詳細說明,這次就暫時不討論伐庭。
Navigation Layer是對參與尋路功能的地圖物體的一個分類粉渠,用層來分類,默認有三個層可以選擇圾另,當然也可以自己添加層霸株。
在Edit下拉列表,選擇Project——NavMeshLayers
出現(xiàn)了NavMesh層的管理界面:
上面三個Buit-in Layer是系統(tǒng)默認的三個可選擇層集乔,我們可以在下面的User Layer里面輸入自己需要的層的名稱去件,比如我現(xiàn)在輸入一個叫做“brigde”的層
這時候坡椒,剛才輸入的“bridge”層,就會出現(xiàn)在可選擇的列表里面
通過剛才的幾步尤溜,NavMesh常用的幾個面板我們都已經(jīng)操作過了倔叼,接下來可以做一個小例子:
在場景里面,我放了一個攝像機(Camera)宫莱,一個充當?shù)孛娴拿嫫╬lane)丈攒,一個角色模型(man)和一個目標點物體(target)
為了便于觀察目標點的位置,我在目標點物體身上添加了Light組件讓它會發(fā)光授霸。角色模型(man)身上必須添加NavMesh組件巡验,不然就不能尋路了。為了方便碘耳,我使用了官方的大兵模型显设,里面已經(jīng)帶有了動畫和動畫控制的腳本。不過這些動畫的表現(xiàn)暫時是不重要的辛辨,你可以選擇放一個膠囊或者Cube代替人物的模型捕捂。
還記得剛開始介紹的Navigation面板嗎?選擇地面(plane)斗搞,在Navigation面板里面里面勾選Navigation Static選項指攒,其他的默認不改動。
然后點擊右下角的Bake面板榜旦。這時候會有一個計算的過程幽七,曾經(jīng)用過烘焙或者遮擋剔除的朋友應(yīng)該對這個過程很熟悉了景殷。
不過和之前兩個功能一樣溅呢,如果你沒有保存場景l(fā)evel,unity會提示你先保存猿挚,然后再bake咐旧。
由于現(xiàn)在場景里面的物體很少,所以Bake的過程很快就結(jié)束了绩蜻。
留意看scene視窗铣墨,現(xiàn)在地面的顏色已經(jīng)發(fā)生改變了,這是因為unity已經(jīng)幫你生成了尋路用的NavMesh網(wǎng)格办绝,由于現(xiàn)在沒有遮擋的阻礙物伊约,所以整個地面都是屬于可以行走的范圍。
寫一個最簡單的控制腳本吧孕蝉,以上是C#屡律,由于很簡單,估計用Js的朋友也能對應(yīng)的寫出來降淮。
簡單的解釋一下超埋,這個腳本是直接拖放到角色(man)身上的,并把場景中的目標物體(target)拖放指定到該腳本的target變量上面進行了賦值。在腳本一開始的時候霍殴,我 先獲取了man身上的NavMeshAgent腳本組件媒惕,然后在Update的過程中,man不斷的進行對target的位移的一個尋路并移動到目標位置的操作来庭。
在進行完以上的操作后妒蔚,你應(yīng)該已經(jīng)可以點擊unity的播放按鈕,然后移動目標物體(target)月弛,這時候角色模型已經(jīng)可以追著目標點跑了面睛。
這里我還做了一個簡單的鼠標點擊plane設(shè)定目標點的功能,由于這個功能不在這次的討論范圍內(nèi)尊搬,所以有興趣的朋友可以自己去百度一下具體的方法叁鉴。
進行到這一步,人物已經(jīng)跑起來了佛寿,但由于沒有遮擋的障礙物幌墓,所以人物只是會直線的行走,看不出尋路的感覺冀泻。接下來我們就做點更復雜的:
在場景里面添加一個Cube做為障礙物常侣,具體的形狀和位置請根據(jù)自己喜歡來調(diào)節(jié),我是把它做成了一個長方形弹渔,并擺在了角色面前胳施。
和剛才對地面的操作差不多,選擇遮擋物Cube肢专,在Navigation面板里面勾選Navigation Static選項舞肆,這次的Navigation Layer要選擇Not Walkable。顧名思義博杖,這是不能行走的意思椿胯,代表了這個Cube是不能通過的。
選擇完成后剃根,我們再次點擊Bake哩盲,又是一個小等待的過程。
Bake完成后狈醉,我們回到scene視窗廉油。
觀察scene視窗,會發(fā)現(xiàn)剛才整個地面都是NavMesh的情況已經(jīng)改變了苗傅,在障礙物的周圍抒线,NavMesh留出了一個缺口,這代表了角色已經(jīng)不能從障礙物身上通過了金吗。
再次點擊unity的播放按鈕
現(xiàn)在可以看到十兢,人物已經(jīng)可以繞著障礙物走了趣竣,我們的目的已經(jīng)順利達到了。
這次的例子就到此結(jié)束了旱物。
在第二節(jié)里遥缕,我會詳細的講解高低落差、爬梯子以及跳躍等較為復雜一點的功能宵呛。然后會在第三節(jié)里面講解分條件的尋路(不同人走不同的路)单匣,以及動態(tài)控制道路(如吊橋)等的功能。
上一節(jié)簡單介紹了NavMesh尋路的基本用法宝穗,這次來介紹一下稍微復雜一點點的高低落差以及跳躍的做法户秤,首先來看看這次的目標:
第一部分是爬樓梯,第二部分是橫向跳躍和往下跳落
不管是爬樓梯逮矛,還是跳躍鸡号,NavMesh都是通過了OffMeshLink來做的。創(chuàng)建OffMeshLink的方法有兩種须鼎,接下來會通過制作上面的例子來進行說明:
為了做這個例子鲸伴,我們預(yù)先在場景里面準備了一些物體:攝像機是必須的,一個作為地面的Plane晋控,然后是F1——F5幾個高低落差不一樣的臺階汞窗,L1和L2是樓梯模型, 控制人物主體man赡译,還有移動的目標點target仲吏。
其中man身上必須帶有NavMesh Agent組件,為了觀察方便在target身上帶了light組件蝌焚。
按照上一節(jié)所講的裹唆,plane和F1——F5臺階在Navigation面板勾選Navigation Static選項,然后Bake综看,觀察Scene視窗品腹,會發(fā)現(xiàn)已經(jīng)生成了我們所要的NavMesh網(wǎng)格岖食,現(xiàn)在我們可以像上一節(jié)那樣在plane上面給人物做尋路和移動了红碑,但人物是不會爬樓梯的。
這時候泡垃,我們找到L1樓梯析珊,在樓梯的開始和結(jié)束的位置放置兩個點,這兩個點只需要拾取它的位移的蔑穴,你可以用empty Gameobject來做忠寻,我這里為了便于觀察,就拿了cube來做存和。開始點命名為startPoint奕剃,結(jié)束點命名為endPoint衷旅。
注意:startPoint和endPoint的位置要稍微比所在的平面高一點點。
接下來介紹第一種生成OffMeshLink的方法纵朋。選擇L1樓梯柿顶,然后在Component下拉選項中選擇Navigation——Off Mesh Link。
選擇后操软,OffMeshLink組件已經(jīng)添加到了L1的身上嘁锯,我們可以在Inspector面板看到:
我們把剛才放置在場景里面的startPoint和endPoint指定到OffmeshLink組件的Start和End位置,其他選項默認不改變
再次Bake
現(xiàn)在我們發(fā)現(xiàn)聂薪,在scene面板里面家乘,在startPoint和endPoint之間生成了一條線,而方向是從startPoint指向endPoint的藏澳。
這時候仁锯,你應(yīng)該可以通過移動目標點讓角色開始爬樓梯了。但爬上去之后角色暫時不能跳下來翔悠,如果把目標點移動到plane上扑馁,角色會順著樓梯爬下來。
我們使用同樣的方法對L2進行生成OffMeshLink凉驻。這時候腻要,角色應(yīng)該可以爬兩層樓梯了。到此第一個目標完成了涝登。
接下來我們進行第二個目標的制作雄家,首先先來分析一下我們的場景:
我們希望人物能從2.5M的高度往下跳,超過2.5M人物就不能跳了胀滚,太高會有危險趟济。然后橫向我們希望人物能跳過2米的溝。
根據(jù)這個設(shè)定咽笼,我們的場景會是這樣的情況:L1和L2只能通過爬樓梯顷编,L2和L3之間可以跳躍,L3——L5是可以往下跳的剑刑。
于是媳纬,我們在Navigation面板里面找到Bake欄,Drop Height(掉落高度)填2.5施掏,Jump Distance(跳躍距離)填2钮惠,單位都是米
接下來介紹第二種生成OffMeshLink的方法:
我們把L1——L5的物體選中,在Navigation面板的Object欄里面把OffMeshLink Generation選項打上勾
再次Bake七芭,回到scene視窗:
這時候素挽,場景里面會出現(xiàn)很多心的OffMeshLink,這是unity通過計算狸驳,把可以跳躍或者下落的地方自動生成了OffMeshLink了预明。
這時候缩赛,你應(yīng)該已經(jīng)可以通過移動目標點,讓角色進行跳躍和下落了撰糠。
進行到這里峦筒,我們的第二個目標也完成了。
不過有些朋友可能會提出疑問窗慎,在做的過程中物喷,假如沒有這個大兵的模型,而是用一個膠囊體來代替人物的話遮斥,它爬樓梯和跳躍的時候好像是在一瞬間完成的峦失,沒有大兵那個爬樓梯和跳躍動作的過程。如這樣:
的確是這樣术吗,因為默認的NaveMesh Agent組件上面是勾選了Auto Traverse Off Mesh Link(自動通過OffMeshLink)選項的尉辑。這樣的意思是人物只要到了OffMeshLink的開始點,就會自動的移動到OffMeshLink的結(jié)束點较屿。
假如各位需要對越過OffMeshLink時候進行自己的控制隧魄,是需要另外寫腳本的。我這里簡單的介紹一下方法隘蝎,有興趣的朋友可以自己試試购啄。
首先各位最好有用狀態(tài)來控制角色的概念。比如人物可以分為站立嘱么、走路狮含、跑步、上下樓梯曼振、橫向跳躍和往下掉落幾種狀態(tài)几迄,針對NavMesh來說,人物簡單的可以分為站立冰评、正常的NavMesh尋路映胁,和通過OffMeshLink移動幾種狀態(tài)。
先把 Auto Traverse Off Mesh Link選項取消甲雅。
然后解孙,當人物在通過OffMeshLink移動的狀態(tài)(可以用NavMeshAgent.isOnOffMeshLink來判斷),獲取到當前通過的OffMeshLink:
OffMeshLinkData??link = NavMeshAgent.currentOffMeshLinkData;
這樣你就能獲取到link的開始點和結(jié)束點的坐標(link.startPos和link.endPos)务荆,這時候你的人物就可以用最簡單的Vector3.Lerp來進行移動妆距,當人物的位移到達了結(jié)束點的坐標,人物的OffMeshLink移動狀態(tài)就可以結(jié)束函匕,又重新變回正常尋路或者站立的狀態(tài)了。在這個Vector3.Lerp的過程中蚪黑,你可以隨意的控制人物的爬行或者跳躍的動作盅惜。
到這里中剩,第二節(jié)的內(nèi)容結(jié)束了。到現(xiàn)在抒寂,各位應(yīng)該已經(jīng)可以基本掌握了NavMesh尋路的全部正常操作了结啼。接下來,我會在第三節(jié)里面簡單講解一下NavMesh的稍微復雜的控制方法屈芜,希望大家繼續(xù)支持阿趙郊愧。
順帶一提,可能很多朋友希望我把工程文件提供下載井佑。不過我覺得這樣并不是一件好事属铁,因為這幾個例子都是很簡單的操作,如果各位有耐心跟著阿趙一步步的做下來躬翁,應(yīng)該可以得到你想要的結(jié)果焦蘑。而如果沒有耐心一步步的看下來,直接看工程文件盒发,可能會忽略了很多重要的步驟的例嘱。
繼續(xù)介紹NavMesh尋路的功能,接下來阿趙打算講一下以下兩個例子宁舰,先看看完成的效果:
第一個例子對于喜歡DOTA的朋友應(yīng)該很熟悉了拼卵,就是不同小隊分不同路線進攻的尋路,紅綠藍三個隊伍分別根據(jù)三條路線進攻蛮艰。
第二個例子是動態(tài)的控制道路的開關(guān)间学。當?shù)鯓虼蜷_時,道路不通印荔,當?shù)鯓蚍畔聲r低葫,道路可以通行。
先來說說第一個例子吧仍律,第一個例子其實很簡單嘿悬,只需要在之前兩節(jié)的基礎(chǔ)上修改一下層的設(shè)置就可以了。
先來分析一下我們的地形水泉,為了做這個例子善涨,我準備了兩個plane分別作為我方基地和地方基地,然后用plane簡單的拼了三條線路草则。
在我方基地钢拧,準備了紅綠藍各三個的小兵(用膠囊代替)。當然小兵身上帶著NavMesh Agent組件
如果把兩個plane和三條線路都打上Navigation static的話炕横,就和普通的尋路沒有區(qū)別源内,三條路都能走。接下來我們進行層的設(shè)置份殿。
還記得第一節(jié)里面講過的怎么設(shè)置NavMeshLayer吧膜钓?
現(xiàn)在我們需要設(shè)置Red嗽交、Blue和Green三個層,如上圖所示颂斜。
現(xiàn)在夫壁,我們可以選擇路線一,然后在Navigation Layer里面選擇Red層了沃疮。相應(yīng)的盒让,路線二選擇Blue層,路線三選擇Green層
Bake出來后司蔬,會是上面的效果邑茄。
道路已經(jīng)設(shè)置好了接下來我們對小兵身上的NavMesh Agent組件進行設(shè)置
選擇藍色的小兵,然后找到NavMesh Agent組件里面的NavMesh Walkable選項葱她,這里就是人物能通過的層的選擇了撩扒。按照剛才層的設(shè)計,藍色的小兵需要勾選Blue層 吨些,把Red層和Green層取消選擇搓谆。
同理,把紅色小兵和綠色小兵的NavMesh Walkable層處理一下豪墅。
現(xiàn)在泉手,我們可以運行了画舌,移動目標點到敵方基地卖子,三種不同顏色的小兵就會根據(jù)不同的路線尋路進攻了。
我們第一個目標也就完成了件缸。
接下來說一下第二個例子
這個例子我準備了兩個平臺屏轰,中間是一個活動的吊橋颊郎,一個帶NavMesh Agent組件的角色模型,一個目標點
如果按照之前的操作霎苗,我們可以輕易的讓角色在任意位置尋路姆吭,但為了讓吊橋升起的時候角色不能通過吊橋,我們需要對吊橋的NavMesh層進行一些設(shè)置唁盏。
和剛才一樣内狸,我們要預(yù)先設(shè)置了一個叫做bridge的層(在第一節(jié)的時候做過)。
同樣的厘擂,吊橋選擇bridge層
這里的操作和上面的例子沒什么區(qū)別昆淡,但這次角色身上的NavMesh Walkable不需要設(shè)置,直接Everything就行了刽严。
到了這里昂灵,我們需要通過腳本來控制人物是否能通過吊橋。這里需要用NavMeshAgent.walkableMask來動態(tài)修改NavMesh Walkable的值。
關(guān)于吊橋怎樣升降倔既,這不是本次討論的內(nèi)容恕曲,你可以選擇直接用位移來控制鹏氧,或者吊橋直接做好開關(guān)的動畫也行渤涌。
之前說過,各位最好要有習慣用狀態(tài)來控制物體把还。這里的吊橋會有2種狀態(tài)实蓬,一種是開狀態(tài),一種是關(guān)狀態(tài)吊履。當開狀態(tài)時安皱,吊橋斷開,人物不能通行艇炎,關(guān)狀態(tài)時酌伊,吊橋閉合,人能通行缀踪。給予這兩種狀態(tài)居砖,我們給人物身上的NavMeshAgent.walkableMask賦值。
寫一段很簡單的代碼吧:
可以了驴娃,就是這么簡單奏候。
這里為了簡便,把賦值寫在了UpDate里面唇敞,其實這樣做是不正確的蔗草,沒必要每幀都檢測賦值,只需要把這個賦值寫在吊橋開關(guān)的控制里面就行了疆柔。
我來解釋一下其中的意思:
定義了一個狀態(tài)的開關(guān)open咒精,當?shù)鯓虼蜷_時open= true;當?shù)鯓蜷]合時旷档,open = false模叙;至于這個狀態(tài)時怎樣賦值的,各位可以自己試試想辦法彬犯。
然后假設(shè)這個腳本是放置角色身上的向楼,那么在start的時候就獲取角色身上的NavMesh Agent組件。當然了谐区,你也可以把腳本放在其他的地方湖蜕,然后通過賦值來指定agent。
當open為true的時候宋列,人物的walkableMask = 1昭抒,意思是只有第一層(就是默認的Default)可以讓玩家通行。
當open為false的時候,人物的walkableMask = -1灭返,意思是所有層(Everything)都可以讓玩家通過盗迟。
從自定義層的界面我們可以總結(jié)一下,每一個層的可通過值熙含,其實就是全面所以層的值相加的總和再加1罚缕。或者說是2的(n-1)次方怎静。
除了指定本身的層意外邮弹,還可以指定多個層,比如這里假如你想mix一個Default和bridge層都能通過蚓聘,你可以設(shè)定walkableMask = 9腌乡,也就是1+8。
到此為止夜牡,阿趙我對于Unity自帶的NavMesh尋路的介紹就結(jié)束了与纽。至于NavMesh或者NavMesh Agent組件的各個屬性和方法,API文檔里面有具體的說明塘装,有興趣可以具體去看看急迂,我就不一一解釋。有很多變化的用法氢哮,各位可以自己嘗試一下袋毙。謝謝大家的支持!
來自作者:阿趙