行為樹是一種在遊戲中常用的實現ai的方式,通過行為樹可行圖形化實現常用的程式結構。
每次執行ai時,從根節點(root)或running節點開始遍歷,父節點執行子節點,子節點執行完後將結果返回父節點,父節點根據子節點的結果來決定接下來怎麼做。行為樹的執行過程就是查詢要執行的葉子節點的過程,查詢的依據就是先執行的葉子節點的結果。通常每個節點有三個狀態:成功(success),失敗(failure),執行中(running)。行為樹的遍歷實際上是一次函式呼叫,立即完成的,但是動作節點的執行確實乙個過程,不能立即完成。這就導致動作節點在為完成之前會被多次執行,因此引入了running狀態,用於表示節點正在執行,每次執行時,跳過之前已經執行完畢的節點,從上次未執行完畢的節點開始執行。但同時需要注意的是,running狀態下ai不會遍歷行為樹,不能影響環境的變化,running節點必須是乙個不可打斷動作節點。
組合節點(composite),從左往右依次執行,類似邏輯與。
1.子節點返回failure,則停止執行,返回failure,下次從根節點開始執行;
2.子節點返回running,則停止執行,返回running,下次從running節點開始執行;
3.子節點返回success,則執行下乙個節點,所有節點都返回success,則返回success,下次從根節點開始執行。
其偽**流程如下:
def sequence_node(owner, node_name):
run_index = get_run_index(node_name)
while run_index < len(child_list):
res = child_list[run_index](owner)
if res == failure:
set_run_index(node_name, 0)
return res
elif res == running:
set_run_index(node_name, run_index)
return res
else:
run_index += 1
set_run_index(node_name, 0)
return success
組合節點(composite),從左往右依次執行,類似邏輯與。
1.子節點返回success,則停止執行,返回success,下次從根節點開始執行;
2.子節點返回running,則停止執行,返回running,下次從running節點開始執行;
3.子節點返回failure,則執行下乙個節點,所有節點都返回failure,則返回failure,下次從根節點開始執行。
其偽**流程如下:
def selector_node(owner, node_name):
run_index = get_run_index(node_name)
while run_index < len(child_list):
res = child_list[run_index](owner)
if res == success:
set_run_index(node_name, 0)
elif res == running:
set_run_index(node_name, run_index)
else:
run_index += 1
set_run_index(node_name, 0)
return failure
組合節點(composite),會依次執行其全部子節點,然後根據所有子節點的返回值,指定該節點的返回值。
其偽**流程如下:
def parallel(owner, node_name):
run_index_list = get_run_index(node_name)
if len(run_index_list) > 0:
for index in run_index_list:
state_dic[index] = child_list[index](owner)
else:
run_index = 0
while run_index < len(child_list):
state_dic[run_index] = child_list[run_index](owner)
run_index += 1
if state_dic.count(success) >= min_success:
return success
elif state_dic.count(failure) >= min_failure:
return failure
else:
return running
組合節點,根據填寫的概率權重,隨機執行其乙個子節點。
其偽**流程如下:
def probability(owner, node_name):
run_index = get_run_index(node_name)
if get_exe_state(node_name) == state_no_running:
weight = random.uniform(0, total_weight)
run_index = 0
for i, w in enumerate(weights):
if weight < w:
run_index = i
break
else:
weight -= w
res = child_list[run_index](owner)
if res == running:
set_run_index(node_name, run_index)
set_exe_state(node_name, state_running)
else:
set_run_index(node_name, 0)
set_exe_state(node_name, state_no_running)
return res
中間節點,對子節點的返回值做相應的裝飾,因此一定會有乙個子節點。
葉子節點(leaf)
條件成立返回success,失敗返回failure。
葉子節點(leaf)
返回success
組合節點都有行為樹的解析器實現,使用者需要自己實現的是葉子節點。
下面使用行為樹節來實現乙個怪物的ai,來演示各邏輯結構如何實現。
順序邏輯結構推擠用順序節點實現,每個子節點都是動作節點。
假設,要實現的ai,先查詢目標,然後攻擊。
if結構:
假設,要實現的ai,如果發現目標,則進行攻擊。
if-else結構:
例如,要實現的ai,如果發現目標,則進行攻擊,否則巡邏。
if-elseif結構:
例如,要實現的ai,如果發現目標,則進行攻擊,如果發現掉落裝備,則撿裝備,否則巡邏。
例如,要實現的ai,如果發現目標,則進行攻擊,如果發現掉落裝備,則撿裝備,否則巡邏。
撿裝備的過程是,移動到裝備所在位置,然後撿裝備。
在移動到裝備位置的過程中,此節點返回running,直達移動到該點,才返回success。在此過程中,迴圈的執行該節點,判斷是否移動到了指定位置。
AI邏輯實現 取捨行為樹還是狀態機
個人體會 狀態機來實現ai更符合我們思維的樸素表達,我想任何乙個有經驗的coder都能直觀得去寫乙個自己的ai狀態機。它用於一些簡單的ai其實是沒有大問題的,搜尋敵人,靠近,攻擊,死亡 用狀態機其實更加便捷。但是面對一些複雜的ai邏輯實現就會顯得比較繁雜。同時,當需要對現有行為邏輯進行擴充套件的時候...
基於行為樹的ai
我們現在做的遊戲,包括手遊,網頁遊戲,ai部分策劃那邊的需求並不複雜 待機,巡邏,行走,逃跑,攻擊,被擊 而且ai需求定了,也不會有太大的改動。所以用狀態機是乙個不錯的選擇,因為狀態機確實很簡單 我們一直都是用狀態機 行為樹,實現ai的另外一種方式,先簡單介紹一下行為樹的概念,然後我們用行為樹的方式...
使用AI來檢測違反社交距離的行為
作者 priya dwivedi 編譯 flin medium 美國和歐洲的許多城市現在都在謹慎地重新開放。人們被要求在外出時保持安全距離。但是人們照著做嗎?城市對人們的安全距離是否符合規則進行評估並採取相應的行動是很重要的。如果大多數人都遵守疫情期間的命令,那麼就可以安全地開放更多的公共場合。然而...