AI角色的復雜決策——行為樹


  本文章轉載自人工智能編程精粹,轉載請注明出處。

簡介

  有限狀態機難以模塊化,編寫代碼麻煩容易出錯。相比較而言,行為樹(Behavior Tree)層次清晰,易於模塊化,並且可以利用通用的編輯器簡化編程,簡潔高效。

  行為樹編輯器在Unity3d商店中就有,可以直接使用,不過大部分都是花錢的。

行為樹技術原理

  行為樹主要采用4種節點來描述行為邏輯,分別是順序節點條件節點選擇節點行為節點。每一棵行為樹表示一個AI邏輯。要執行其邏輯,需要從根節點開始遍歷執行整棵樹。

  節點從結構上分為兩類:組合節點、葉節點。

    組合節點:樹中間的節點。

    葉節點:沒有孩子的節點,一般用來放置執行邏輯和條件判斷。

  葉節點

    葉節點包括兩種類型節點,分別是條件節點和行為節點

    1.條件節點

      可以理解為if條件測試,用來測試當前是否滿足某些性質或條件,例如:“玩家是否在20米之內?”

      如果條件測試結果為真,那么向父結點返回success,否則返回failure

    2.行為節點

      用來完成實際的工作,例如:播放動畫、規划路徑、讓角色移動位置、感知敵人、更換武器、播放聲音、增加生命值等。

      在執行這種節點的時候,可能只需要一幀,也可能需要多幀。

      絕大部分動作節點會返回success。

  組合節點

    用來控制數的遍歷方式,最常用的組合節點有選擇節點、順序節點、並行節點、修飾節點等

    1.選擇節點

      也稱為優先級Selector節點,它會從左到右依次執行所有子節點,只要子節點返回failure,就繼續執行后續子節點,直到有一個節點返回success或running為止,這時它會停止后續子節點的執行,向父節點返回success或running。若所有子節點都返回failure,那么它向父節點返回failure。

      需要注意的是,當子節點返回running時選擇節點會“記錄”返回running的這個子節點,下個迭代會直接從該節點開始執行(行為節點對應的代碼執行時間較長,這時返回running

// C#偽代碼 Selector節點

for (int i = 0; i < n; i++)
{
    state = Tick(child(i));
    if (state == Running)
        return Running;
    if (state == Success)
        return Success;
}
return Failure;

    2.順序節點

      它會從左到右依次執行所有子節點,只要子節點返回success,它就繼續執行后續子節點,直到有一個節點返回failure或running為止,這時它會停止后續子節點的執行,向父節點返回failure或running。若所有子節點都返回success,那么它向父節點返回success。

      它與選擇節點正好是相反的感覺(選擇節點類似於解決怎么進入這個房間如“爆破”、“踹門”,而順序節點類似於解決能不能成功做這一件事如“爆破”,我有沒有炸彈包,引線,火源

// C#偽代碼 Sequence節點

for (int i = 0; i < n; i++)
{
    state = Tick(child(i));
    if (state == Running)
        return Running;
    if (state == Failure)
        return Failure;
}
return Success;

    3.隨機選擇節點

      前面提到的兩種組合節點都是有優先級的,最左面的節點優先級最高,然而對於隨機選擇節點,它不是永遠按照從左到右的順序執行,而是會隨機選擇訪問子節點的順序。

    4.修飾節點

      修飾節點值包含一個子節點,用於以某種方式改變這個子節點的行為。

      修飾節點有很多種,其中有一些是用於決定是否允許子節點運行的,這種修飾節點有時也稱為過濾器,例如Until Success,Until Fail等。Until Success的行為是這樣的:循環執行子節點,直到子節點返回success為止。

      例如,檢測“視線中是否有敵人”,在修飾節點的作用下,會不停地檢測,直到發現敵人為止。

      Limit節點用於指定某個子節點的最大運行次數。例如:如果子節點的連續運行次數小於3,那么如果大於等於3返回failure。

      Time節點設置了一個計數器,它不會立即執行子節點,而是等待一段時間,時間到了才開始執行。

    5.並行節點(Parallel)

      有多個子節點,與順序節點不同的是,這些子節點的執行是並行的——不是一次執行一個,而是同時執行,直到其中一個返回failure(或全部返回successs)為止。此時,並行節點向父節點返回failu(或success),並終止其它所有子節點的執行。

      並行節點用在如下一幀發生了某種事件,需要打斷這些節點的執行。這種情況顯然順序節點是無法實現的,而並行節點可以實現,因為並行必須保證所有結點為success

  子樹的復用

    游戲中可能有多種的AI,需要不同的行為樹,但是可能它們的行為樹中的戰斗系統是一樣的,這時,為了避免重復工作,就可以復用戰斗的子樹。

  使用行為樹與有限狀態機的權衡

    行為樹和有限狀態機在游戲AI中已經十分常見,但它們並不能互相代替,所以應用的時候加以權衡,了解它們不同的適用性。

    (1)對於狀態機來說,每個時刻都是出於某種“狀態”,等待某個事件(轉換)的發生。本質上是“事件驅動”的,即周圍游戲世界發生的“事件”驅動角色的“狀態”變化。從實現上來看,狀態機既可以采用輪詢的方式實現(每幀主動查詢是否發生了某種事件),也可以采用事件驅動的方式實現(例如,注冊一個回調函數,每當事件發生時,調用這個函數,在其中改變狀態機的狀態,或是利用消息,當事件發生時,發送消息)。

    (2)對於行為樹,處理周圍游戲世界的變化的任務是由條件節點來完成的,這相當於每次遍歷行為樹時,條件節點都向周圍世界發出某種“詢問”,以這種方式來監視游戲世界發生的事情。因此,這實際上是“輪詢”的方式——不斷的主動查詢。雖然目前已經有了一些高級的技術,能夠將事件的驅動集成在行為樹中,但在實現中,絕大多數行為樹都是自頂向下,采用輪詢的方式實現的。

    (3)一般來說,行為樹不太適合需要事件驅動的行為。例如AI角色需要對大量的外部事件作出反應——當AI角色正在向某個目標移動時,突然發生了某個事件,如同伴需要救援,玩家被擊中等事件,需要立即終止這個移動過程,需要重新做出新的決策等。在遇到這種情況的時候,還是在狀態機和行為樹直間好好做一下權衡。

  行為樹執行時的協同(Coroutine)

    也就是所謂的行為節點的多幀執行。在Unity中就用StartCoroutine開啟協同程序就好了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM