尋路演算法:NPC 為什麼會卡牆
這裡要先建立一個重要觀念:導航資料結構描述的是「AI 認為可以走的地方」,而物理碰撞體描述的是「角色實際能不能穿過去的地方」。 這兩者如果沒有同步,NPC 就會出現「導航上這裡是路、物理上這裡是牆」的致命矛盾,也就是最經典的貼牆卡死。
尋路 ≠ 移動:路徑規劃與轉向控制的雙層架構
很多新手開發者會以為「找到路徑就等於會走」,但實際上 NPC 的移動至少牽涉三層:
卡牆最常發生的地方,往往不是第一層,而是第二層與第三層。因為路徑規劃是在抽象圖上進行的,它不知道「平滑後的曲線會切過牆角」,也不知道「角色轉向半徑太大,過不了那個九十度彎」。這也是為什麼很多 NPC 的行為看起來像「明明知道路,卻走得亂七八糟」——它的腦袋知道路,但身體不聽話。
二、NPC 卡牆的十大元凶
接下來這十個原因,涵蓋了從資料層、演算法層到行為層的常見翻車現場。你可以把它當成一份除錯清單,遇到 NPC 卡住時,從上往下逐一排查,命中率通常不低。
元凶一:路徑節點與碰撞體不一致
這是最經典、也最常見的原因。導航網格烘焙時,場景中的牆體、欄杆、箱子如果沒有被正確標記為「靜態幾何(Static Geometry)」,就會被烘焙流程忽略,導致導航網格直接穿過牆體。於是 NPC 的尋路結果告訴它「往前直走可以到」,但物理引擎說「不行,這裡有牆」。NPC 就會不斷嘗試往前走,撞牆、被推回、再往前走,形成貼牆抖動的畫面。
反過來也有另一種情況:導航網格烘焙得太保守,把一些實際上可以通過的窄縫判定為不可走,NPC 就會莫名其妙地繞一大圈,或者在狹窄處來回猶豫。這類問題通常要在開發階段用視覺化工具把 NavMesh 疊在場景上檢查,才看得出破洞在哪。
元凶二:啟發函數(Heuristic)設計錯誤
前面提過,A* 的效能與正確性都依賴啟發函數。如果 h(n) 估得太高,A* 會變得貪婪,可能找到一條「看起來很近、實際很繞」的路徑;如果 h(n) 跟移動模型不匹配(例如在六角格地圖用曼哈頓距離),路徑品質就會下降。更麻煩的是,某些專案為了效能會刻意使用「權重式 A*(Weighted A*)」,把 h 乘以一個大於 1 的係數來加速搜尋,代價就是路徑可能不是最短,NPC 就容易走出貼牆的彆扭路線。
元凶三:動態障礙物沒有重算路徑
靜態場景烘焙好之後,一旦遊戲中出現會移動的障礙物——關起來的門、被推倒的書架、臨時生成的岩漿池——原本的路徑就作廢了。如果 AI 沒有機制去偵測「路徑上出現新障礙」,NPC 就會照著舊路徑一頭撞上去。有些引擎提供 NavMesh Obstacle 元件,可以在障礙物出現時挖掉(Carve)對應區域並要求附近角色重算路徑,但這個功能有成本,很多專案會設定「只對玩家附近生效」或「每隔幾秒才更新一次」,於是就出現 NPC 卡在動態門口的經典畫面。
元凶四:路徑平滑化(Path Smoothing)切過牆角
這是很多開發者會忽略的隱形殺手。A* 產生的原始路徑是沿著網格中心的折線,看起來很機械,所以大家會做平滑化,把它變成漂亮的曲線。但問題是:平滑後的曲線可能切進牆角。特別是當路徑在轉角處有兩個相鄰節點,平滑演算法為了圓滑,會把曲線往內側拉,結果就是 NPC 的實際移動軌跡穿過了牆體邊緣,被物理引擎擋住,然後它就卡在那裡了。
正確的做法是在平滑化之後,對每一段曲線做碰撞檢測(例如 Capsule Cast),確認整條平滑路徑都在可行走區域內;或者改用「弦切角」受限的平滑演算法,限制曲線與原始路徑的最大偏移量。
元凶五:尋路網格解析度不足
格子太大,窄門就會被判定為不可通行;格子太小,記憶體與搜尋成本又會暴增。這個取捨在手機遊戲或大型開放世界中特別明顯。有些專案會用「多層解析度」來折衷:大格子做粗尋路,小格子只在角色附近做細部修正。但如果兩層之間的連結沒有處理好,NPC 就會在粗細網格的交界處迷路,出現「明明看得到門卻走不進去」的狀況。
另一個相關參數是 Agent Radius(角色半徑)。如果你的 NPC 是體型較大的 Boss,但導航網格是用小兵半徑烘焙的,那麼 Boss 就會不斷嘗試穿越它實際上過不去的通道,然後卡死。這是很多動作遊戲 Boss 戰卡牆的主因之一。
元凶六:轉向半徑與避障邏輯衝突
尋路演算法通常假設角色可以「原地轉向」或「瞬間改變方向」,但實際的轉向控制(Steering)會給角色一個最大轉向角速度與最小轉向半徑。當路徑要求 NPC 做一個急轉彎,而它的轉向半徑又不夠小時,它就會衝過頭、撞牆,然後試圖回頭,形成來回擺盪的抽搐行為。
同樣的問題也會發生在群體避障(RVO、ORCA)上。當多個 NPC 同時擠向一個窄門,避障演算法會互相把對方推開,導致某些 NPC 被推離原路徑、撞上牆壁,而它們的狀態機又沒有「重新尋路」的機制,於是就永遠卡在牆邊。
元凶七:多執行緒與非同步尋路的時序問題
現代遊戲為了效能,尋路通常會丟到背景執行緒(Worker Thread)去算,算完再把結果送回主執行緒套用。這就產生了「路徑過期(Stale Path)」的問題:當背景執行緒花了 50 毫秒算出路徑時,目標可能已經移動了,或者玩家已經把門關上了。如果系統沒有用版本號、時間戳或「目標位移閾值」來判斷路徑是否還有效,NPC 就會拿著一張過期的地圖導航,然後撞牆。
更糟的是,如果多個尋路請求同時進行,而結果回傳的順序錯亂,NPC 可能會拿到「上一個目標」的路徑,然後往錯誤的方向跑。這類 Bug 在測試環境很難重現,但在玩家電腦上卻層出不窮。
元凶八:狹窄通道與群體推擠
當十幾個 NPC 同時要通過一扇窄門,而每個角色都有碰撞體積時,就會出現「瓶頸死鎖」:大家互相卡住,誰也過不去。這種情況在攻城戰、村莊巡邏、或是寵物跟隨系統中特別常見。解決方式包括設定優先級(讓隊長先走)、排隊機制、或是讓部分角色暫時關閉碰撞(但這會產生穿模的副作用),需要針對遊戲體驗做取捨。
元凶九:NavMesh 烘焙(Bake)參數不當
NavMesh 烘焙有一堆參數,每一個都可能讓 NPC 卡牆:
Cell Size: 決定網格精度,太粗會漏掉細節。
這些參數必須根據遊戲中所有角色的體型與移動能力來設定。如果你的遊戲同時有小老鼠 NPC 和巨龍 Boss,通常需要烘焙多張不同 Agent 設定的 NavMesh,並在執行時動態切換。
元凶十:狀態機與尋路中斷
最後一個常見原因是行為邏輯本身的 Bug。NPC 的行為通常由狀態機(State Machine)或行為樹(Behavior Tree)控制,例如「巡邏 → 發現敵人 → 追擊 → 攻擊」。如果狀態切換時沒有正確清理舊路徑,或者攻擊動畫鎖住了移動輸入,NPC 就可能出現「站在牆邊一直播放攻擊動畫」或「路徑已清空卻仍在原地轉圈」的狀況。這類問題通常要搭配行為日誌(Behavior Log)與視覺化狀態機來除錯。
三、實戰案例:那些年我們一起卡住的 NPC
理論講完了,來看看幾個玩家最有感的實際案例。這些情境幾乎涵蓋了前面十種元凶的組合,也是各大遊戲論壇上最常被回報的 Bug 類型。
案例一:城門口永遠走不進去的衛兵
某款 MMO 的玩家發現,主城門口的衛兵會在巡邏到城門時卡住,貼著門框左右抖動,永遠走不進城內。追查後發現,城門是動態物件(會定時開關),而製作團隊只在城門「開啟」狀態下烘焙了 NavMesh,卻沒有處理「關閉」狀態的導航更新。當城門關上時,衛兵的路徑仍然穿過門的位置,於是它就一頭撞上門板,尋路系統每幀都告訴它「往前走」,物理系統每幀都把它推回來,形成永恆的抖動。
這類 Bug 的修法通常有兩種:一是把城門設為 NavMesh Obstacle,關閉時自動挖掉該區域並觸發周邊角色重算路徑;二是改用觸發器(Trigger)在門關閉時直接讓衛兵切換巡邏路線。前者彈性高但成本較大,後者簡單但需要針對每個場景手動設定。
案例二:Boss 戰中穿牆失敗的追擊型敵人
動作遊戲中常見的大型 Boss,在追擊玩家時會試圖直接穿過柱子或矮牆,結果卡在障礙物旁邊。原因通常有兩個:第一,Boss 的 Agent Radius 遠大於小兵,但專案只烘焙了一張以一般角色為準的 NavMesh,導致 Boss 的尋路結果穿越了它實際上過不去的狹窄通道;第二,Boss 的轉向半徑太大,即使路徑正確,它也無法在狹窄空間內完成轉彎。
進階的解法是為 Boss 單獨烘焙一張 Agent 較大的 NavMesh,或者在狹窄處設置「Boss 不可進入」的導航遮罩(NavMesh Modifier),讓尋路系統直接避開這些區域。有些遊戲甚至會讓 Boss 在卡住超過一定時間後,直接播放「破牆」或「瞬移」的演出,把 Bug 轉化成遊戲特色。
案例三:跟隨型寵物在樓梯間的抽搐
寵物跟隨是幾乎每款 RPG 都會做的功能,也是最容易卡牆的地方。常見情境是:玩家走上樓梯,寵物在後面跟隨,卻在樓梯轉角處卡住,一下往上、一下往下,像在跳機械舞。這通常是因為樓梯的 Step Height 設定不當,階梯被判定為「可跨越」與「不可跨越」的邊界地帶,導致尋路結果在相鄰兩階之間反覆跳動。
另一個原因是跟隨邏輯的目標點更新太頻繁。如果寵物每一幀都重新計算到玩家位置的路径,而玩家又在移動,路徑就會不斷被覆寫,寵物永遠走不完第一段路徑。比較好的做法是設定「路徑重算閾值」——只有當玩家移動超過一定距離,或寵物偏離路徑超過一定角度時,才重新尋路。
四、玩家視角:遇到 NPC 卡牆怎麼辦
身為玩家,我們無法修改遊戲程式碼,但還是可以透過一些操作來「繞過」AI 的Bug。以下幾個方法在多數遊戲中都有一定效果:
常見遊戲內的破解手法
回報 Bug 的正確姿勢
如果你希望這個問題被修好,回報時請盡量提供:遊戲版本、角色座標、當時的任務狀態、NPC 名稱、以及一段能重現的錄影。最好能附上「重現步驟」,例如「從村莊東門沿著圍牆走,護送 NPC 到鐵匠鋪時必定卡在第二個轉角」。對開發團隊來說,有座標與影片的 Bug 回報,修復效率會比「NPC 卡住了」高出十倍以上。
五、開發者視角:如何避免 NPC 卡牆
如果你正在開發遊戲,以下幾件事可以大幅降低 NPC 卡牆的機率。它們不見得能解決所有問題,但至少能讓你在 Bug 發生時快速定位。
除錯工具與視覺化
第一件事:把 NavMesh、路徑、Agent 狀態全部畫出來。Unity 的 NavMesh 視覺化、Unreal 的 Navigation Mesh 顯示、以及自行用 Gizmos 繪製路徑點與轉向向量,都是基本配備。當你能看到「AI 認為可以走的地方」與「實際碰撞體」之間的差異,八成以上的卡牆原因會立刻現形。
第二件事:建立導航圖的連通性檢查。在關卡載入時,自動檢查所有應該互相連通的區域是否真的連通,並在編輯器或測試報告中標記出來。很多卡牆問題其實是關卡設計改動後,NavMesh 沒有重新烘焙造成的,自動化檢查可以提早攔截這類錯誤。
設計層面的防呆
再好的 AI 也會有出錯的時候,所以遊戲設計上要有「保險機制」:
最後,把「NPC 卡住」當成一種必然會發生的狀況來設計,而不是假設它不會發生。很多 3A 遊戲都會在 NPC 卡住超過一定時間後,直接讓它傳送到最近的導航點,或者播放一個「我迷路了」的語音來掩蓋,這不是偷懶,而是務實的工程取捨。
結語:卡牆不是 Bug,是演算法與世界的對話
NPC 卡牆看起來像是一個簡單的程式錯誤,但背後其實是尋路演算法、導航資料、物理碰撞、轉向控制與行為邏輯五個系統之間的複雜互動。任何一個環節的參數歪掉,或是任何兩個系統之間的假設不一致,都會讓 NPC 在玩家面前演出各種荒謬的卡牆喜劇。
對玩家來說,理解這些原理之後,下次看到 NPC 貼牆抽搐,也許就能會心一笑,甚至猜到是哪個參數沒調好;對開發者來說,把導航網格、路徑平滑與轉向控制當成一個整體來設計,並加上足夠的視覺化與防呆機制,才是讓 NPC 真正「走得像人」的關鍵。畢竟,一個不會卡牆的 NPC,才是玩家願意相信它真的存在于那個世界裡的第一步。
如果你在遊戲裡遇到什麼奇葩的 NPC 卡牆現場,歡迎在雅寶社區 · 頂客論壇的遊戲攻略版分享,附上影片與座標,說不定下一個被我們拆解的案例,就是你的親身經歷。
```