尋路建模的三種方式比較

概述

本文對於遊戲尋路中主流的三種建模方式做了比較,分析各自的適用範圍和優缺點。這三種建模方式包括:格子(Grid)、路點(Waypoint)、導航網格(Navmesh)

寫這篇的原因是項目裏需要選擇一種合適的尋路實現方案,查閱了大量的文章和算法後,結合着自己的思考和實踐,在此做個小結。

這裏的建模指的是爲地圖尋找一個空間表徵(spatial representation)1,即把原始地圖轉換成計算機數據結構表示的模型,用於後面的尋路。注意它與尋路算法2是不同的概念,例如:Grid和Navmesh是兩種不同的建模方式,但是建模完成後,都可以用到A*算法。

下面是三種建模方式的圖形化表示,一目瞭然,分別是:(a) 原版地圖,(b) 格子,(c) 路點,(d) 導航網格。

這裏寫圖片描述

先來一個簡單而粗略的比較,後面再分頭細說:

  • 實現複雜度:導航網格 > 格子 > 路點
  • 內存和計算開銷3:格子 > 導航網格 > 路點
  • 表達精確性:導航網格 > 格子 > 路點

格子(Grid)

這種方法將原始地圖分割成許多的小格子,在計算機中表示爲一個二維數組,用0和1分別表示障礙和可行走區域。

格子的優點
  • 容易實現
  • 容易動態修改。如果需要動態加入障礙,只需要確定障礙物會佔用哪些格子,再重新尋路即可。
格子的缺點
  • 內存和計算開銷大。越大的地圖,所需格子就越多,相應的內存佔用和尋路計算開銷就會越大。另外,格子的大小選擇也是一個問題,定得小了,內存和計算開銷大;定得大了,又會縮減可行走區域,導致可行走邊界不夠精確。
  • 可能需要做額外平滑。如果按照格子來尋路,最後生成的路線很可能會出現90度的拐角,甚至可能有連續的多個,這種急轉彎會使得遊戲尋路表現得“不夠自然”。這時還需要做額外的平滑。
  • 不太適合3D地圖。格子最早是針對2D地圖尋路提出的,不涉及高度信息,因此沒有導航網格中的maxClimbagentHeight等參數,更沒有考慮分層地圖。當然也不是完全不能做,只是更復雜。

路點(Waypoint)

這種方法會在地圖中標註一些路點,尋路只能發生在路點和路點之間,在計算機中表示爲一張連通圖。

路點的優點
  • 實現簡單
  • 內存和計算開銷低。路點只使用到了真實可行走區域的一小部分,與格子相比,犧牲了路線的靈活性,換取較低的內存和計算開銷。
路點的缺點
  • 需要人工參與。因爲需要人工標註路點位置和可行走路線。
  • 侷限性較大。首先,路點的靈活性較低,尋路必須沿着預先定義好的路線前進,使用時有時會發現:明明有看上去更直接的路線,卻偏偏只能繞遠路走折線;其次,對於起始點不在路點圖中的情況,還需要找到最近的路點先移動過去;最後,路點不考慮實際的底層地圖,所以在移動過程中有可能出現被物體阻擋卡住的情況。

導航網格(Navmesh)

這種方法使用一系列算法將原始地圖轉換成三角形網格的集合,網格和網格之間構成連通關係用於尋路。在計算機中表示爲頂點的集合,以及三個頂點索引一組(邊)的集合。

導航網格的優點
  • 能精確地表徵世界。雖然導航網格也做不到百分百還原真實地圖,但是它無疑比格子和路點都更精確。首先,它引入了高度信息,使得表示3D地圖成爲可能;其次,它在應用agentRadiusagentHeight等參數時用到了體素(voxel)4,這是一種比格子更小的計量單元,使得計算可行走範圍時更加精確。
  • 內存和計算開銷小。導航網格將地圖抽象成三角網格,也就是頂點和邊的集合。理論上,這種建模方式的複雜度介於路點和格子之間。
導航網格的缺點
  • 複雜,難以實現和修改。自己從頭實現一個導航網格系統無疑是非常複雜的,這需要很多幾何算法的知識。好在現在有一些開源的實現,如crisis的引擎工程師實現的recast-navigation5。但如果想在它基礎上去修改和定製,還是要花費不少功夫。
  • 建立網格的過程耗時耗內存。與格子和路點不同,前兩者從原始地圖建模的過程幾乎是瞬間完成的,而建立導航網格則是一個相對複雜和耗時的過程,其中體素化這一步又會佔用不少內存(完成後會釋放掉)。好的網格導航實現可以將建網格和動態加入障礙的時間代價控制在幾毫秒的級別。通常的程序實現會在第一次尋路前就尋找時機建好網格。

總結

每種建模方式都有自己的優點和缺點,應具體根據應用場景選擇合適的方式。

如果開發時間有限,需要在可能動態變化的2D地圖中尋路,地圖不會太大,內存充足,且對行走區域的精確度沒有太高要求,首選格子。

如果開發時間有限,尋路線路相對固定(典型的如塔防遊戲),不用考慮真實地形的影響,優先考慮路點。

如果開發時間充裕,地圖很大,對錶徵真實世界的精確度要求很高,那麼最好選擇導航網格。


  1. 本文寫作過程中參考了《遊戲人工智能》中的《選擇一個尋路空間表徵》一文。
  2. 遊戲中的常用尋路算法參見文章
  3. 這裏只針對尋路本身,不包括建模的過程,否則導航網格的開銷會更大
  4. 參見我翻譯的有關體素化的文章
  5. 參見我寫的專欄:recast源碼解析
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章