基於行為樹的AI框架
阿新 • • 發佈:2019-02-03
所謂AI即人工智慧,例如掃蕩副本,boss,小怪有智慧地攻擊玩家等pve(player vs Environment)的地方都會用到。程式可以設計不同的AI來調整難度,讓boss小怪顯得更加有智慧。實現AI的方式有很多種,從有限狀態機(FSM),分層有限狀態機(HFSM)到決策樹(Decision Tree),都可以維護龐大數量的知識條目。本文要介紹的是Next-Gen AI的行為樹(Behavior Tree)。
行為樹(Behavior
Tree) 具有如下的特性:
它只有4大型別的Node:
* Composite Node 組合節點
* Decorator Node 裝飾節點
* Condition Node 條件節點
* Action Node 行為節點
任何Node被執行後,必須向其Parent Node報告執行結果:成功 / 失敗。
這簡單的成功 / 失敗彙報原則被很巧妙地用於控制整棵樹的決策方向。
其中,組合節點有順序節點(SequenceNode有一個子節點返回false就結束,相當於與運算)和選擇節點(SelectorNode有一個子節點返回true就結束,相當於或運算)兩種,條件節點和行為節點屬於葉子節點,即沒有子節點。光說文字很難理解。一個比較有名的AI行為樹如下
下面是一個專案中用到的AI行為樹框架
類繼承關係如下
根據上面各節點的描述,有以下流程圖。
具體的虛擬碼如下
using System; public enum State { INIT, //初始化 PENDING, //正在執行 FINISH, //成功 FAIL //失敗 } //基類BTNode public class BTNode { State state; ComponentNode parent; public virtual void reset() { state = State.Init; } //執行方法,用於過載override public virtual void execute(AIControl agent) { } public virtual void finish(AIControl agent, State stat) { this.state = stat; if(this.parent!=null) { //把state傳給父節點 this.parent.tryMoveNext(agent, stat); } } } //複合節點 public class ComponentNode:BTNode { List<BTNode> childs; //子節點 bool isFirstExe; //是否第一次執行,用於初始化 addChild(){};//新增子節點 removeChild(){};//移除子節點 override finish(){base.finish();} moveNext() { if(CanMoveNext()) { nextChild.execute(); } else { moveEnd(); } } //先判斷條件是否能執行下一個子節點再執行 tryMoveNext(State stat) { if(checkState(stat)) { moveNext(); } } override execute() { if(isFistExe){isFirstExe = false;beforeFirstExecute();} moveNext(); } virtual beforeFirstExecute(){}//用於初始化 virtual checkState(){}//用於override virtual moveEnd(){} //用於override } public class SequenceNode : ComponentNode { override bool checkState(State stat) { if(stat == State.Fail) { finish(State.fail); return false; } return true; } override void moveEnd() { finish(State.finish); } } public class SelectorNode : ComponentNode { override bool checkState(State stat) { if(stat == State.finish) { finish(State.finish); return false; } return true; } override void moveEnd() { finish(State.Fail); } } public class BehaviorNode:BTNode { } //條件節點 class ConditionNode : BehaviorNode { override void execute() { if(condition()) { finish(State.finish); } else { finish(State.fail); } } virtual bool condition(){} } //行為節點 class ActionNode:BehaviorNode { virtual void execute() { finish(State.pending); } } //具體實現的選擇節點 class xxx:SelectorNode { override void beforeFirstExecute(){} override void execute(){} } //具體實現的順序節點 class yyy:SequenceNode { override void beforeFirstExecute(){} override void execute(){} } //具體實現的條件節點 class yyy : ConditionNode { override bool condition(){} } //具體實現的行為節點 class zzz:ActionNode { override void execute(){} } //AIControl存放一顆AI行為樹的根節點,每隔一段時間從根節點遍歷行為樹,根據當前的情況實現不同的分支葉子節點,從而實現具體的遊戲邏輯 class AIControl { root = 讀表根節點 think() { 每隔一段時間 root.execute(this); } }
以上是一個底層的行為樹基本框架,具體的程式實現,需要根據策劃的需求,實現各個具體的節點,一般是繼承選擇節點,順序節點,條件節點,行為節點用得比較多。一些需要迴圈執行等特殊操作的裝飾類節點在專案中比較少用,在這裡也就沒有具體實現了。專案中通過讀取策劃匯出的約定好的AI行為樹檔案,在邏輯層呼叫AIControl.think實現遊戲物件有智慧地思考行動。