遊戲開發中怪物AI實現方案總結!

遊資網發表於2019-10-25
在遊戲開發中實現怪物AI邏輯的主要技術有兩種:1、狀態機 2、行為樹。他們兩者的實現機制不一樣,其中狀態機是“事件”機制,行為樹是“輪詢”機制。在專案開發中可以根據具體情況合理的選擇兩者來處理AI編寫問題。

這篇文章分兩個部分對遊戲中的AI進行講解,1、狀態機,2、行為樹。

概述

開發遊戲AI的目標之一就是要找到一個簡單,可擴充套件的編輯邏輯的方案,從而加速遊戲開發的迭代速度。在“行為系統圖”中,行為系統(Behavior System)響應遊戲中的各種資訊,進行決策以挑選接下來將要執行的行動並且監控該行動的執行。

遊戲開發中怪物AI實現方案總結!

知識模型(Knowledge Model)是對遊戲世界中各種資訊的抽象。

在行為系統中,有限狀態機(FSM,Finite State Machine)最為經典,FSM模型的優勢之一是簡單。但是FSMs需要用轉換(Transition)連線狀態(State),因此,狀態(State)失去了模組性(Modularity)。

遊戲開發中怪物AI實現方案總結!

行為樹,英文是Behavior Tree,簡稱BT,是由行為節點組成的樹狀結構:

遊戲開發中怪物AI實現方案總結!

對於FSM,每個節點表示一個狀態,而對於BT,每個節點表示一個行為。同樣是由節點連線而成,BT有什麼優勢呢?

在BT中,節點是有層次(Hierarchical)的,子節點由其父節點來控制。每個節點的執行都有一個結果(成功Success,失敗Failure或執行Running),該節點的執行結果都由其父節點來管理,從而決定接下來做什麼,父節點的型別決定了不同的控制型別。節點不需要維護向其他節點的轉換,節點的模組性(Modularity)被大大增強了。實際上,在BT裡,由於節點不再有轉換,它們不再是狀態(State),而是行為(Behavior)。

第一種-有限狀態機

1、有限狀態機(FSM)的實現方式有三種:

程式導向的方式的if else

用列舉配合switch case語句。

用多型與虛擬函式(也就是狀態模式)

2、狀態模式的經典定義:允許物件在當內部狀態改變是改變其行為,就好像物件改變了自己的類一樣。

3、狀態模式的實現分為三個要點:

為狀態定義一個介面

為每個狀態定義一個類

恰當地進行狀態委託

4、通常來說,狀態模式中狀態物件的存放有兩種實現存放思路:

靜態狀態。初始化時把所有可能的狀態都new好,狀態切換時通過賦值改變當前的狀態

例項化狀態。每次切換狀態時動態new出新的狀態。

關於FSM的具體案例如下:

1、Unity的Mecanim動畫系統就是通過狀態模式來實現的

遊戲開發中怪物AI實現方案總結!

2、下圖是一個簡單的戰鬥過程的狀態機,如果用狀態模式實現他的攻擊邏輯就非常的方便,而且支援後期狀態的擴充套件。

遊戲開發中怪物AI實現方案總結!

總結:狀態模式暫時沒有找到好的開源框架,但是狀態模式不僅僅在AI方面使用,在遊戲的框架中也被廣泛使用,比如:UI框架,遊戲主邏輯狀態框架等等。

第二種-行為樹

什麼是行為樹

如果瞭解過狀態機,會知道在行為樹之前,在實現AI用得比較多的技術是狀態機,狀態機理解起來是比較簡單的,即一個狀態過渡到另一個狀態,通過判斷將角色的狀態改變即可,如果學習過Unity的Mecanim動畫系統,會更加直觀的理解。但是狀態機在狀態較多的情況下會使狀態之間的切換變得異常繁瑣,同時狀態之間很難複用。在這種情況下,行為樹被髮明出來,行為樹的優點如下:

1、行為樹提供大量的流程控制方法,使得狀態之間的改變更加直觀;
2、整個遊戲AI使用樹型結構,方便檢視與編輯;
3、方便除錯和程式碼編寫;
4、更好的封裝性和模組性,讓遊戲邏輯更直觀,開發者不會被那些複雜的連線繞暈。
5、最重要的:行為樹方便製作編輯器,可以交由策劃人員使用;

行為樹的基本概念:

1、執行每個節點都會有一個結果(成功,失敗或執行)
2、子節點的執行結果由其父節點控制和管理
3、返回執行結果的節點被視作處於執行狀態,處於執行狀態的節點將被持續執行一直到其返回結束(成功或失敗)。在其結束前,其父節點不會把控制轉移到後續節點。

行為樹原理

行為樹是一種樹形結構,所以其可以分成3種節點型別:

遊戲開發中怪物AI實現方案總結!

1、紅色的節點:根節點,沒有父節點的節點;
2、藍色的節點:組合節點,有父節點和子節點的節點;
3、白色的節點:葉節點,沒有子節點的節點;

節點的返回

每個節點都會有一個返回值,可能出現的返回值有3個,如下:

1、執行中:表示當前節點還在執行中,下一次呼叫行為樹時任然執行當前節點;
2、失敗:表示當前節點執行失敗;
3、成功:表示當前節點執行成功;

下面我們來細說一下這幾個節點:

根節點

行為樹的入口節點,可以是任意型別的節點;

組合節點

行為樹的組合節點是由下面幾種型別來組成的:

1、選擇節點/優先選擇節點(Selector)

該節點會從左到右的依次執行其子節點,只要子節點返回“失敗”,就繼續執行後面的節點,直到有一個節點返回“執行中”或“成功”時,會停止後續節點的執行,並且向父節點返回“執行中”或“成功”,如果所有子節點都返回“失敗”則向父節點返回“失敗”。

2、隨機選擇節點(Random Selector)

之前的選擇節點是有優先順序順序的,而隨機選擇節點的執行順序是隨機的。但每個節點只會執行一次,比如包含子節點:A、B、C、D、E;使用隨機選擇節點,執行順序可能是:D、E、A、C、B或其他組合。其它規則同選擇節點一致。

3、順序節點(Sequence)

該節點會從左到右的依次執行其子節點,只要子節點返回“成功”,就繼續執行後面的節點,直到有一個節點返回“執行中”或“失敗”時,會停止後續節點的執行,並且向父節點返回“執行中”或“失敗”,如果所有子節點都返回“成功”則向父節點返回“成功”。

4、修飾節點(Decorator)

修飾節點只包含一個子節點,用來以某種方式來改變這個子節點的行為。修飾節點的型別比較多,這裡我們說一些比較常見的修飾節點:

1、Until Success和Until Failure

迴圈執行子節點,直到返回“成功”或“失敗”為止。

比如Until Success在子節點返回“執行中”和“失敗”時都會向父節點返回“執行中”,返回“成功”時向父節點返回“成功”。

Until Failure在子節點返回“執行中”和“成功”時都會向父節點返回“執行中”,返回“失敗”時向父節點返回“成功”。

2、Limit

執行子節點一定次數後強制返回“失敗”。當子節點執行指定次數後還沒有返回“失敗”則該節點向父節點返回失敗。

3、Timer

子節點不會立即執行,而會在指定的時間到達後才開始執行。

4、TimeLimit

指定子節點的最長執行時間,如果子節點在指定時間到達後還在執行則強制返回“失敗”。

5、Invert

對子節點的返回結果取“非”,即子節點返回“成功”則該節點返回“失敗”,子節點返回“失敗”則該節點返回成功。

5、並行節點(Parallel)

不同於選擇和順序節點依次執行每個節點,並行節點是“同時”執行所有的節點,然後根據所有節點的返回值判斷最終返回的結果。

這裡的“同時”會迷惑住不少人,實際上,行為樹是執行在單一執行緒上的,並不會在並行節點上開多個執行緒來進行真正的同時執行,那麼“同時”的含義是什麼?

我們知道選擇或順序節點會依次執行所有的子節點,當子節點返回“成功”或“失敗”後就會停止後續節點的執行,而並行節點也會依次執行所有的子節點,無論子節點返回“成功”或“失敗”都會繼續執行後續節點,保證所有子節點都得到執行後在根據每個子節點的返回值來確定最終的返回結果。

並行節點一般可以設定退出該節點的條件,比如:

1、當全部節點都返回成功時退出;
2、當某一個節點返回成功時退出;
3、當全部節點都返回成功或失敗時退出;
4、當某一個節點返回成功或失敗時退出;
5、當全部節點都返回失敗時退出;
6、當某一個節點返回失敗時退出;

葉節點

1、條件節點(Condition)

條件節點可以理解為一個if判斷語句,當條件的測試結果為true時向父節點傳遞success,結果為false時向父節點傳遞failure;

該節點搭配一些組合節點可以完成各種判斷跳轉,比如搭配順序節點,可以做出“是否看見敵人”->“向敵人開火”的AI;

2、行為節點(Action)

行為節點用來完成具體的操作,比如,移動到目標點,執行開火等程式碼邏輯,多種情況下行為節點會返回running和success;行為節點也可能會使用多幀來完成;

子樹的複用

我們設計好的行為樹可以在其他樹中作為一顆子樹來進行使用,最大可能的複用子樹可以減少開發量。

總結:行為樹的框架,網上有比較好的案例,如騰訊開源的behaviac。

Github地址:github.com/Tencent/beha

遊戲開發中怪物AI實現方案總結!


原文:https://zhuanlan.zhihu.com/p/87035778

相關文章