天天看點

NavMesh系統動态碰撞的探讨

  Unity3D提供的NavMesh系統可以友善的解決遊戲的尋路問題,但是該系統有一個比較讓人不了解的問題:

  NavMesh導航時會忽略Physics系統本身的碰撞,也就是說NavMeshAgent在移動的過程中不會被Collider阻擋,而是會直接走過去(但是OnTriggerEnter等觸發功能正常)。

  動态碰撞的功能對很多遊戲都是一個基本的需求,而根據NavMesh提供的接口,唯一可以實作阻擋功能的隻有NavMeshObstacle,而NavMeshObstacle隻有一種形狀:圓柱體,而且up方向固定,不能調整為側向。總結起來就是以下幾點:

  (1)導航網格的行走/碰撞區域隻能預烘焙;

  (2)動态碰撞體隻能通過挂載NavMeshObstacle元件來實作;

  (3)碰撞體的形狀隻有一種——圓柱體,嚴格來說就是圓形,而且是正圓還不能是橢圓。

  是以說到這裡,基本上可以放棄使用各種形狀的Collider來制作場景阻擋物了。不過,替代方案也還是有的:如果一定要使用Unity3D提供的NavMesh來做導航,那麼可以将圓作為基本元素來模拟其它形狀。

  

NavMesh系統動态碰撞的探讨

  上圖展示了通過NavMeshObjstacle來模拟立方體阻擋物,為了友善的編輯該立方體的大小,可以寫一個輔助腳本來實作:

  上述代碼可以調整Obstacle的個數和間距,然後再配合調整縮放比例基本上可以做出各種尺寸的立方體。

  單向阻擋的實作,可以通過組合Trigger和NavMeshObstacle來實作一個單向阻擋的功能:

NavMesh系統動态碰撞的探讨

  實作思路是當角色進入紅色Trigger區域時,将後面的阻擋物隐掉,過1秒之後再激活,這樣就可以實作一個單向阻擋物的功能,實作的代碼比較簡單,如下面所示:

 >>>>>>經測試,上述方案并不是很好用,會碰到以下幾個問題:

(1)角色在Obstacle周圍擠來擠去,行為很詭異;

(2)通過不斷地靠近Obstacle,當遇到卡頓的時候,角色會穿透阻擋物;

(3)Obstacle雖然可以設定Cave屬性,也就是動态切割導航面,但由于一些原因,動态切割的效果非常差,尤其是在一些不平的地面部分更是如此。

基于這些思考,推薦使用如下新的方法來做阻擋效果:

  通過NavMesh的Layer來實作:

NavMesh系統動态碰撞的探讨

  通過動态改變NavMeshAgent所能使用的層(NavMeshWalkable),來實作雙向和單向阻擋的效果,經驗證這種方案表現效果比較好,隻是在場景制作時就必須确定不同層區域的劃分。

  上述方案再配合一些魔法牆之類的特效,總體來說表現效果還是不錯的,不過代碼邏輯一定要清晰。