個人體會:
狀態機來實現ai更符合我們思維的樸素表達,我想任何乙個有經驗的coder都能直觀得去寫乙個自己的ai狀態機。它用於一些簡單的ai其實是沒有大問題的,(搜尋敵人,靠近,攻擊,死亡)用狀態機其實更加便捷。但是面對一些複雜的ai邏輯實現就會顯得比較繁雜。同時,當需要對現有行為邏輯進行擴充套件的時候,**上就會顯得比較吃力,因為要維護的狀態量會成倍增加。
行為樹,實現ai的過程更加得有技巧,框架設計者較為全面考慮了我們可能會遇到的種種情況,把每種情況都抽象成了乙個型別的節點,而我們要做的就是按照規範去寫節點,然後把節點連線成一顆行為樹。更加得具有物件導向的味道,行為模組間的藕合度相對較低。
舉個粗糙的例子來比較一下兩者的不同:
ai行為:吃飯 睡覺 打豆豆(很消耗體力和腦力的;)
1.打豆豆 hp -= 5 / 秒 mp -= 3 / 秒
2.吃飯 hp += 10/秒 mp -= 1 / 秒
3.睡覺 mp += 15/秒 hp -= 2/秒
4.吃飯和睡覺是不可打斷的動作(pending),必須執行到吃飽(hp = 100) or 睡飽(mp = 100)
5.打豆豆是瞬發動作,每幀都可以執行一次
狀態機的實現邏輯圖:
行為樹的實現邏輯圖:
其實不管你知不知道什麼是selector,condition都不要緊,至少從上圖,應該可以看出來,行為樹節點間的聯絡並不像狀態機那樣得「緊密」。
選擇兩種不同的ai實現方法,也決定了具體行為的實現邏輯。
比如對於sleep動作的實現,如果是狀態機:
function sleep() =
if y == 100 then
awakeevent()
return
end
hp -= x
mp += y
end
然後每一幀執行sleep()
如果是選擇行為樹:
function sleep()
local sleeptime = (100/15)
–不好意思亂入了一段cocos2dx的**
self:runaction(cc.sequence:create(cc.delaytime:create(sleeptime),cc.callfunc:create(cancelpending)))
local cancelpending = function()
pending = false
end
end羅列一下行為樹的概念:
對於有限狀態機而言,必須明確 狀態的轉換方式;對於行為樹,必須明確狀態前提:前提條件
每乙個行為必須有「前提條件」 ,這決定了該行為是否被選擇。
行為樹的運算也是通過幀迴圈的update來驅動,不一定是每幀都update,但是要週期性update。
每一次run從根節點(root)開始,每一執行都會選擇乙個可行的子節點執行,這種選擇可以是隨機方式,也可以是預設好優先條件
行為樹由葉子節點和中間節點組成,葉子節點是最基本的行為(如跑動,攻擊),中間節點代表邏輯單元(巡邏,逃跑)。
當乙個葉子節點被選擇後,就會啟用其對應的基本的行為
最基本的行為可能執行成功也可能失敗。
高等級的行為(中間節點)是否執行成功依賴於他們的孩子節點是否執行成功。
乙個子節點失敗可能導致父母節點擊擇另外乙個孩子。
除了選擇(selector)乙個單獨的子節點行為,乙個節點還可能順序(sequence)or並行(concurrent)得執行他的所有子節點。
乙個行為除了有前提條件,可能還有上下文條件(父節點or孩子節點可能儲存一定的狀態變數)。
高優先順序的行為可能搶占低優先順序的行為
各種節點的詳細描述:
* selector node 選擇節點
描述:從頭到尾,按順序選擇第乙個執行條件為真的子節點,遇到true停止。
處理流程:當執行本型別node時,它將從begin到end迭代執行自己的child node:如遇到乙個child node執行後返回true,那停止迭代,本node向自己的parent node也返回true;否則所有child node都返回false,那本node向自己的parent node返回false。
從**實現的角度來談下優缺點
優點:
1. 行為邏輯和狀態資料分離,任何節點寫好以後可以反覆利用
2. 重用性高,可用通過重組不同的節點來實現不同的行為樹
3. 呈線性的方式擴充套件,易於擴充套件
4. 可配置,把工作交給designer
5. 能夠勝任」ai」 「掉寶」等等場景。
AI之用行為樹來實現邏輯
行為樹是一種在遊戲中常用的實現ai的方式,通過行為樹可行圖形化實現常用的程式結構。每次執行ai時,從根節點 root 或running節點開始遍歷,父節點執行子節點,子節點執行完後將結果返回父節點,父節點根據子節點的結果來決定接下來怎麼做。行為樹的執行過程就是查詢要執行的葉子節點的過程,查詢的依據就...
邏輯行和物理行
物理行是你在編寫程式時所 看見 的。邏輯行是python 看見 的單個語句。python假定每個 物理行 對應一 個 邏輯行 邏輯行的例子如print hello world 這樣的語句 如果它本身就是一行 就像你在編輯器中看到的那樣 那麼它也是乙個物理行。預設地,python希望每行都只使用乙個語...
邏輯行計數
問題描述 有乙個軟體公司常常用一種不為人知的語言來開發程式,這個語言的特點如下 有兩種形式的字串,一種為加單引號,另一種加雙引號。單引號的字串可以包含雙引號,雙引號的字串也可以包含單引號。字串不能分行,其中也不能包含同樣的引號字元。有兩種注釋方式 字元為行注釋,而雙括號 內的文字為塊注釋。塊注釋不能...