【Unity 插件推薦】從零學習 AI 行動大師,用 Behavior Designer 打造頂尖 BOSS!

目錄
【Unity 插件推薦】從零學習 AI 行動大師,用 Behavior Designer 打造頂尖 BOSS!

 

前言

 

在製作遊戲的過程中,AI 行為樹行為樹是實現角色智能行為的重要工具,而 UnityBehavior Designer 插件可以幫助開發者高效構建 BOSS 的 AI 行為樹。原文作者提供了不少的例子,並自己琢磨實現一個簡單的 BOSS 的 AI 行為樹,並把思路分享出來,各位小夥伴可以依據這些思路進行再擴展,除了附上簡易的使用教學】還附上實用的補充說明】,希望能激發大家的創意並提升開發效率,也歡迎大家支持原文作者!

 

【Unity 插件推薦】從零學習 AI 行動大師,用 Behavior Designer 打造頂尖 BOSS!

 

 

插件介紹

 

Behavior Designer 是 Unity 的一款功能強大的行為樹插件,設計目的是讓策劃、程式設計師和美術人員能夠更輕鬆地建立 NPC 行為邏輯。它通過直觀的可視化編輯器,使 AI 系統的開發變得簡單和高效,即使不具備編程經驗的使用者也能上手使用。

 

Behavior Designer Logo 圖片

 

功能特色

  • 視覺化編輯器通過直觀的圖形界面,使用者可以方便地創建、修改和管理 NPC 行為樹,無需編寫複雜代碼。
  • 可擴展性:提供強大的 API 支持,開發者可以編寫自定義的 task(任務)以擴展插件的功能。
  • 與其他插件兼容可與 UScriptPlayMaker 等插件結合使用,快速構建複雜 AI 系統。
  • 豐富的內建 task:內置眾多常用行為樹節點,可以輕鬆地實現各種 AI 行為邏輯,如重複、選擇和條件檢查等。

 

適用場景

  • 角色扮演遊戲(RPG): Behavior Designer 可用於設計敵人 AI、夥伴角色的支援行為,以及村莊或城市中 NPC 的日常互動行為,讓遊戲世界更具沉浸感。尤其適用於官邸 BOSS 設計,讓 BOSS 擁有多階段變化、策略性技能和智能反應,增強戰鬥挑戰。
  • 射擊遊戲(FPS/TPS): 可用於設計敵人的掩護、巡邏、追擊和逃跑等行為,讓敵人表現出更戰術化的反應,增強遊戲的挑戰性與真實感。
  • 策略遊戲(RTS/SLG): 利用行為樹為不同的單位設計智慧化的指揮和協作行為,例如資源收集、軍隊部署、敵人偵查等,讓 AI 單位能做出合理的策略性反應。

 

 

事前準備

 

插件可以在 AssetStore 下載到。

Behavior Designer 插件下載點

 

插件可以在 AssetStore 下載到。

 

目前最新的版本是 1.7.2。

 

目前最新的版本是 1.7.2。

 

可以在官網查看每個版本的迭代內容。

Behavior Designer 官方網站

 

可以在官網查看每個版本的迭代內容。

 

學習插件的時候,建議先看下官方文件。


線上文檔

Behavior Designer 官方線上文件
 

官方線上文件

 

離線文檔

插件的 Behavior Designer 目錄中有個 Documentation.pdf 文檔,不過可能很多同學都沒去看這份文檔,建議還是看一看。

 

插件的 Behavior Designer 目錄中有個 Documentation.pdf 文檔,不過可能很多同學都沒去看這份文檔,建議還是看一看。

 

 

插件介面

 

打開編輯器

點擊菜單 Tools/Behavior Designer/Editor 即可開啟編輯器窗口。

 

點擊菜單 Tools/Behavior Designer/Editor 即可開啟編輯器窗口。

 

開啟後可以看到畫面如下。

 

開啟後可以看到畫面如下。

 

介面介紹

介面可以劃分為 3 個區域,如下。

 

介面可以劃分為 3 個區域,如下。

 

第 1 個區域是行為樹的組織區域,我們的行為樹節點是在這個區域上進行連線的。

 

第 1 個區域是行為樹的組織區域,我們的行為樹節點是在這個區域上進行連線的。

 

第 2 個區域頂部是四個標籤頁:Behavior、Tasks、Variables、Inspector,預設是 Tasks 標籤頁,顯示的是節點清單。

 

第 2 個區域頂部是四個標籤頁:Behavior、Tasks、Variables、Inspector,預設是 Tasks 標籤頁,顯示的是節點清單。

 

標籤頁說明
Behavior整個行為樹的設置,例如行為樹名稱、是否啟動時立即執行、執行完畢後是否重新執行等設置。
Tasks任務節點列表,例如 Composities(符合節點)、Decorators(裝飾節點)、Actions(行為節點)等等。
Variables行為樹變量,可以設定全域變量,也可以設定行為樹本身的變量。
Inspector查看節點詳細信息,設定節點參數。

 

第 3 個區域按鈕功能如下。

 

第 3 個區域按鈕功能如下。

 

第 3 個區域按鈕功能如下。

 

 

快速製作一棵行為樹

 

在講解節點之前,我先示範一次如何快速製作一棵行為樹,讓大家對整個流程有個概念。

 

創建物體

首先在場景中創建一個物體,可以是任何物體,例如你想控制角色,那麼這個物體就可以是你的角色模型,這裡我會創造一個空物體。

 

重命名為 BehaviorTreeObj。

 

重命名為 BehaviorTreeObj。

 

重命名為 BehaviorTreeObj。

 

掛 BehaviorTree 腳本

開啟 Behavior Designer 編輯器,先選取剛剛的 BehaviorTreeObj 物體,然後在編輯器網格空白處右鍵滑鼠,點選選單 Add Behavior Tree。

 

開啟 Behavior Designer 編輯器,先選取剛剛的 BehaviorTreeObj 物體,然後在編輯器網格空白處右鍵滑鼠,點選選單 Add Behavior Tree。

 

這一步其實是給物體掛上 BehaviorTree 組件,我們也可以透過 Add Component 手動加入 BehaviorTree 組件。

 

這一步其實是給物體掛上 BehaviorTree 組件,我們也可以透過 Add Component 手動加入 BehaviorTree 組件。

 

新增 Task 節點

 

我以最簡單的 Log 節點為例,它的功能就是輸出日誌,在空白處點擊滑鼠左鍵,按鍵盤的空格键即可彈出節點搜尋框,搜索 log,可以看到 Log 節點,點擊即可建立出 Log 任務節點,它會自動幫我新增一個 Entry 入口節點,Entry 連向 Log,如下。

 

我以最簡單的 Log 節點為例,它的功能就是輸出日誌,在空白處點擊滑鼠左鍵,按鍵盤的空格键即可彈出節點搜尋框,搜索 log,可以看到 Log 節點,點擊即可建立出 Log 任務節點,它會自動幫我新增一個 Entry 入口節點,Entry 連向 Log,如下。

 

我們給 Log 節點設定 Text 字段的值為 Hello World,並添加註釋,如下。

 

我們給 Log 節點設定 Text 字段的值為 Hello World,並添加註釋,如下。

 

運行測試

運行 Unity,可以看到 Log 節點被執行了,顯示了一個綠色的勾,日誌視窗也輸出了 HelloWorld。

 

運行 Unity,可以看到 Log 節點被執行了,顯示了一個綠色的勾,日誌視窗也輸出了 HelloWorld。

 

導出 BehaviorTree

點選 Export 按鈕,將行為樹匯出儲存為資源文件。

 

點選 Export 按鈕,將行為樹匯出儲存為資源文件。

 

如下,這樣子就可以重複使用行為樹資源了。

 

如下,這樣子就可以重複使用行為樹資源了。

 

手動引用 BehaviorTree 樹資源

 

設定 External Behavior

我們把上面導出的行為樹資源賦值給 BehaviorTree 元件的 External Behavior 成員,如下。

 

我們把上面導出的行為樹資源賦值給 BehaviorTree 元件的 External Behavior 成員,如下。

 

執行時,就會根據這個 External Behavior 的行為樹來執行了。

 

使用 Behavior Tree Reference

另外,我們也可以透過 Behavior Tree Reference 節點來引用行為樹資源, 先建立一個 Behavior Tree Reference 節點,點擊 Inspector,設定它引用的外部行為樹資源即可
 

另外,我們也可以透過 Behavior Tree Reference 節點來引用行為樹資源, 先建立一個 Behavior Tree Reference 節點,點擊 Inspector,設定它引用的外部行為樹資源即可。

 

一般我們會做一個通用的行為樹保存為資源文件,然後對特殊的怪物另外做行為樹,並讓其引用通用行為樹資源,像這樣子
 

一般我們會做一個通用的行為樹保存為資源文件,然後對特殊的怪物另外做行為樹,並讓其引用通用行為樹資源,像這樣子。

 

動態載入行為樹資源並設定 External Behavior

 

我們也可以透過程式碼動態設置 External Behavior,我在這裡使用 Addressables 插件來做資源加載。

首先將行為樹資源檔案新增 Addressable 管理,分配到一個 Addressable 索引名,如下。

註:勾上 Addressable 就會自動分配一個索引名了

 

首先將行為樹資源檔案新增 Addressable 管理,分配到一個 Addressable 索引名,如下。

 

接著我們可以使用程式碼載入行為樹資源,動態賦值給 BehaviorTree 元件的 ExternalBehavior 對象, 並建立一個 AddBehaviorTree.cs 腳本。

 

接著我們可以使用程式碼載入行為樹資源,動態賦值給 BehaviorTree 元件的 ExternalBehavior 對象, 並建立一個 AddBehaviorTree.cs 腳本。

 

程式碼如下。

 

using System.Collections;

using UnityEngine;

using BehaviorDesigner.Runtime;

using UnityEngine.AddressableAssets;

public class AddBehaviorTree : MonoBehaviour

{

   IEnumerator Start()

   {

       // 初始化 Addressables

       yield return Addressables.InitializeAsync();

       // 添加行為樹組件

       var bt = gameObject.AddComponent<BehaviorTree>();

       // 設定為不立即執行

       bt.StartWhenEnabled = false;

       // 加載行為樹資源

       var loader = Addressables.LoadAssetAsync<ExternalBehaviorTree

("Assets/BtRes/Behavior.asset");

       yield return loader;

       // 設定 ExternalBehavior

       bt.ExternalBehavior = loader.Result;

       // 啟用行為樹

       bt.EnableBehavior();

   }

}
 

我們建立一個空物體,重新命名 BtObj,並給它掛上 AddBehaviorTree 腳本,如下。

 

我們建立一個空物體,重新命名 BtObj,並給它掛上 AddBehaviorTree 腳本,如下。

 

我們運行 Unity,可以看到 BtObj 物體動態掛了 BehaviorTree 組件,並且動態設定了 ExternalBehavior 對象,行為樹也被執行了,輸出了 Hello World,如下。

 

我們運行 Unity,可以看到 BtObj 物體動態掛了 BehaviorTree 組件,並且動態設定了 ExternalBehavior 對象,行為樹也被執行了,輸出了 Hello World,如下。

 

我們可以點擊 BehaviorTree 組件上的 Open 按鈕。

 

我們可以點擊 BehaviorTree 組件上的 Open 按鈕。

 

可以看到行為樹已經執行完畢。

 

可以看到行為樹已經執行完畢。

 

如果我們想讓行為樹執行完畢後重複執行,可以設定 RestartWhenComplete 為 true。

 

如果我們想讓行為樹執行完畢後重複執行,可以設定 RestartWhenComplete 為 true。

 

我們串一個 Wait 節點,方便觀察。

 

我們串一個 Wait 節點,方便觀察。

 

執行效果如下,可以看到行為樹可以重複執行了。

 

執行效果如下,可以看到行為樹可以重複執行了。

 

上面我們用到了 Squence 順序節點,它是一個複合節點,下文我會進行節點的詳細介紹。

 

 

複合節點:Composities

 

行為樹任務節點中最重要的節點就是複合節點了,它決定了行為樹的執行流,也就是 Tasks 列表中 Composities 分組的這些節點。

 

行為樹任務節點中最重要的節點就是複合節點了,它決定了行為樹的執行流,也就是 Tasks 列表中 Composities 分組的這些節點。

 

我先簡單做個日常生活的行為樹給大家看看,如下。

 

我先簡單做個日常生活的行為樹給大家看看,如下。

 

上面的行為樹的執行過程是怎麼樣的呢?想要搞清楚就得先知道行為樹的執行順序:從左到右,且深度優先。 

另外,複合節點又控制著子節點的執行規則,是順序執行還是並行執行,亦或者隨機執行,是遇到成功就立即返回成功還是遇到失敗就立即返回失敗,亦或者遇到成功繼續執行下一個,或遇到失敗繼續執行下一個呢?這些都是複合節點來控制的,這裡頭的邏輯需要大家好好琢磨,下面我帶大家挨個過一遍複合節點,講解過程中我會穿插順帶講解一下用到的其他任務節點,並舉一些實際的應用場景,方便大家學以致用,也希望大家能夠觸類旁通。 

 

Sequence:順序節點

 

節點介紹

 

顧名思義,順序節點就是從左到右挨個順序執行,當所有子節點都返回 Success 時,它才會返回 Success。

 

顧名思義,順序節點就是從左到右挨個順序執行,當所有子節點都返回 Success 時,它才會返回 Success。

 

顧名思義,順序節點就是從左到右挨個順序執行,當所有子節點都返回 Success 時,它才會返回 Success。

 

當某個子節點返回 Failure 時,順序節點就會立刻返回 Failure。

 

當某個子節點返回 Failure 時,順序節點就會立刻返回 Failure。

 

新髮口訣

順序節點,由左至右,為真繼續,全真才真,一假即假,一假即停。
類似於與邏輯。

 

案例 1:通知開飯了

我們使用 Has Received Event 來監聽開飯的事件,當它檢測收到事件時才會返回 Success,此時順序節點就會去執行下一個子節點,即乾飯的邏輯,達到響應事件的功能,如下。

 

我們使用 Has Received Event 來監聽開飯的事件,當它檢測收到事件時才會返回 Success,此時順序節點就會去執行下一個子節點,即乾飯的邏輯,達到響應事件的功能,如下。

 

其中 Has Received Event 節點要設定監聽的事件名稱,定義一個字串即可。

 

其中 Has Received Event 節點要設定監聽的事件名稱,定義一個字串即可。

 

拋出事件有兩種方式,一種是程式碼呼叫行為樹的 SendEvent 接口,如下。

 

public void SendEvent(string name);

public void SendEvent<T>(string name, T arg1);

public void SendEvent<T, U>(string name, T arg1, U arg2);

public void SendEvent<T, U, V>(string name, T arg1, U arg2, V arg3);

 

範例:

 

// bt是BehaviorTree對象

bt.SendEvent("EAT_EVENT");

 

另外一種是使用 SendEvent 節點。
 

另外一種是使用 SendEvent 節點。

 

設定要傳送的事件名稱即可。

 

設定要傳送的事件名稱即可。

 

案例 2:吃幾口飯吃一口菜

想像你吃飯的過程,扒拉吃幾口飯,然後吃一口菜,我們可以用順序節點來組織。

 

想像你吃飯的過程,扒拉吃幾口飯,然後吃一口菜,我們可以用順序節點來組織。

 

Parallel:平行節點

 

節點介紹

 

並行節點,顧名思義,它會並行執行所有的子節點,所有的子節點都返回 Success,並行節點才會返回 Success。

 

並行節點,顧名思義,它會並行執行所有的子節點,所有的子節點都返回 Success,並行節點才會返回 Success。

 

並行節點,顧名思義,它會並行執行所有的子節點,所有的子節點都返回 Success,並行節點才會返回 Success。

 

只要有一個子節點返回 Failure,並行節點就會立刻返回 Failure。如下圖,我們可以看到,等 10 秒和等 20 秒的兩個節點還沒執行完就被停止了,因為中間那個等 1 秒的節點執行完畢並返回了 Failure 給並行節點,整個並行以 Failure 結束,那些被終止的 Wait 也會直接返回 Failure。

 

只要有一個子節點返回 Failure,並行節點就會立刻返回 Failure。如下圖,我們可以看到,等 10 秒和等 20 秒的兩個節點還沒執行完就被停止了,因為中間那個等 1 秒的節點執行完畢並返回了 Failure 給並行節點,整個並行以 Failure 結束,那些被終止的 Wait 也會直接返回 Failure。

 

新髮口訣

並行節點,並行執行,全真才真,一假即假,一假即停,被停即假。

 

案例:邊跑步邊聽歌

例如我們邊跑步邊聽歌,同時還要監聽是否有下雨,有下雨的話要中斷跑步,如下。

 

例如我們邊跑步邊聽歌,同時還要監聽是否有下雨,有下雨的話要中斷跑步,如下。

 

這個例子我用到了 Selector 節點,並且啟用了 Self 中斷,看不懂的同學不要著急,下文我會講。

 

Selector:選擇節點

 

節點介紹

 

選擇節點與順序節點類似,也是從左到右執行,不同的是,當有子節點返回 Success,選擇節點就會立刻返回 Success,不會執行下一個子節點。

 

選擇節點與順序節點類似,也是從左到右執行,不同的是,當有子節點返回 Success,選擇節點就會立刻返回 Success,不會執行下一個子節點。

 

選擇節點與順序節點類似,也是從左到右執行,不同的是,當有子節點返回 Success,選擇節點就會立刻返回 Success,不會執行下一個子節點。

 

如果子節點返回 Failure,會就執行下一個子節點,其實很好理解,就是從左到右遍歷選一個 Success,有 Success 就返回 Success,否則執行下一個子節點。

 

如果子節點返回 Failure,會就執行下一個子節點,其實很好理解,就是從左到右遍歷選一個 Success,有 Success 就返回 Success,否則執行下一個子節點。

 

如果所有子節點都返回 Failure,選擇節點才返回 Failure。

 

如果所有子節點都返回 Failure,選擇節點才返回 Failure。

 

新髮口訣

選擇節點,由左至右,一真即真,一真即停,全假才假。

 

案例:詐騙檢舉機率

例如收到詐騙簡訊後,99% 有的機率會執行檢舉,1% 有的機率會上當受騙,如下。

 

例如收到詐騙簡訊後,99% 有的機率會執行檢舉,1% 有的機率會上當受騙,如下。

 

Parallel Selector:並行選擇節點

 

節點介紹

 

顧名思義,就是並行執行選擇節點,有一個 Success 就立即返回 Success,並且會終止其他子節點,被終止的子節點會返回 Failure,如下。


顧名思義,就是並行執行選擇節點,有一個 Success 就立即返回 Success,並且會終止其他子節點,被終止的子節點會返回 Failure,如下。

 

顧名思義,就是並行執行選擇節點,有一個 Success 就立即返回 Success,並且會終止其他子節點,被終止的子節點會返回 Failure,如下。

 

所有子節點都返回 Failure 時,並行選擇節點才返回 Failure。

 

所有子節點都返回 Failure 時,並行選擇節點才返回 Failure。

 

新髮口訣

並行選擇節點,並行執行,一真即真,一真即停,全假才假。

 

案例:考試研究和找工作

現在人生道路有兩條路:考試研究、找工作,同時進行,其中一件事情成了,就吃一頓好的慶祝一下,如下。

 

現在人生道路有兩條路:考試研究、找工作,同時進行,其中一件事情成了,就吃一頓好的慶祝一下,如下。

 

Priority Selector:優先權選擇節點

 

節點介紹

 

這個節點和 Selector 類似,Selector 的執行順序是從左到右,而 Priority Selector 會先檢查子節點的優先權(priority)進行排序,優先順序高的優先執行。 問題來了,我們要如何設定子節點的優先權呢?節點的優先順序預設是 0,如果要修改優先權,需要重寫 Task 的 GetPriority 方法。

 

這個節點和 Selector 類似,Selector 的執行順序是從左到右,而 Priority Selector 會先檢查子節點的優先權(priority)進行排序,優先順序高的優先執行。 問題來了,我們要如何設定子節點的優先權呢?節點的優先順序預設是 0,如果要修改優先權,需要重寫 Task 的 GetPriority 方法。

 

這個節點和 Selector 類似,Selector 的執行順序是從左到右,而 Priority Selector 會先檢查子節點的優先權(priority)進行排序,優先順序高的優先執行。 問題來了,我們要如何設定子節點的優先權呢?節點的優先順序預設是 0,如果要修改優先權,需要重寫 Task 的 GetPriority 方法。

 

這裡我封裝一個有優先權參數的日誌節點吧:PriorityLog,建立一個 PriorityLog 腳本,程式碼如下。

 

using System.Collections;

using UnityEngine;

using BehaviorDesigner.Runtime;

using UnityEngine.AddressableAssets;

public class AddBehaviorTree : MonoBehaviour

{

   IEnumerator Start()

   {

       // 初始化 Addressables

       yield return Addressables.InitializeAsync();

       // 添加行為樹組件

       var bt = gameObject.AddComponent<BehaviorTree>();       // 設定為不立即執行
 

       bt.StartWhenEnabled = false;

       // 加載行為樹資源

       var loader = Addressables.LoadAssetAsync<ExternalBehaviorTree

("Assets/BtRes/Behavior.asset");

       yield return loader;

       // 設定 ExternalBehavior

       bt.ExternalBehavior = loader.Result;

       // 啟用行為樹

       bt.EnableBehavior();

   }

}
 

現在我們就可以在 Tasks 清單中看到我們新封裝的 PriorityLog 節點了。

 

現在我們就可以在 Tasks 清單中看到我們新封裝的 PriorityLog 節點了。

 

使用它連個簡單的行為樹,如下。

 

使用它連個簡單的行為樹,如下。

 

我們可以選取節點,在 Inspector 中設定節點的 Priority。
 

我們可以選取節點,在 Inspector 中設定節點的 Priority。

 

由於右邊的節點優先權我們設定為了 1,比左邊的節點優先權高,所以會優先執行右邊的節點,因為右邊的節點執行返回了 Success,此時 Priority Selector 就會直接返回 Success,不會去執行左邊的節點了,如下。

 

由於右邊的節點優先權我們設定為了 1,比左邊的節點優先權高,所以會優先執行右邊的節點,因為右邊的節點執行返回了 Success,此時 Priority Selector 就會直接返回 Success,不會去執行左邊的節點了,如下。

 

新髮口訣

優先權選擇節點,優先權排序,一真即真,一真即停,全假才假。

 

案例:先吵架還是先道歉

我先給行為樹創建一 Foat 類型的變數:SorryPriority,如下。

 

我先給行為樹創建一 Foat 類型的變數:SorryPriority,如下。

 

以它作為道歉優先變量。

 

以它作為道歉優先變量。

 

接著製作如下的行為樹,當按下 A 鍵的時候,設定 SorryPriority 變量,提高道歉的優先級。

 

接著製作如下的行為樹,當按下 A 鍵的時候,設定 SorryPriority 變量,提高道歉的優先級。

 

接著製作如下的行為樹,當按下 A 鍵的時候,設定 SorryPriority 變量,提高道歉的優先級。

 

接著製作如下的行為樹,當按下 A 鍵的時候,設定 SorryPriority 變量,提高道歉的優先級。

 

道歉節點的 Priority 參數設定為 SorryPriority 變量,如下。
 

道歉節點的 Priority 參數設定為 SorryPriority 變量,如下。

 

我們運行,如果我沒有按下 A 鍵,則道歉優先級是 0,2 秒情緒醞釀完畢後,會默認先執行吵架。

 

我們運行,如果我沒有按下 A 鍵,則道歉優先級是 0,2 秒情緒醞釀完畢後,會默認先執行吵架。

 

如果我在 2 秒情緒醞釀期間按下了 A 鍵,則會設定道歉優先變數為 1,情緒醞釀完畢後就會優先執行道歉,就不會吵架了

 

如果我在 2 秒情緒醞釀期間按下了 A 鍵,則會設定道歉優先變數為 1,情緒醞釀完畢後就會優先執行道歉,就不會吵架了

 

Random Selector:隨機選擇節點

節點介紹

 

這個很好理解,按選擇節點的規則,只是不是從左到右執行,而是隨機順序執行。

 

這個很好理解,按選擇節點的規則,只是不是從左到右執行,而是隨機順序執行。

如果有子節點返回 Success,則立即返回 Success,否則繼續執行下一個節點。

 

如果有子節點返回 Success,則立即返回 Success,否則繼續執行下一個節點。

 

只有所有的子節點都返回 Failure 時,Random Selector 才會返回 Failure。

 

只有所有的子節點都返回 Failure 時,Random Selector 才會返回 Failure。

 

新髮口訣

隨機選擇節點,隨機執行,一真即真,一真即停,全假才假。

 

案例:吃米飯、麵條、餃子

中午吃什麼好?隨機選一個吧,好的,吃麵~

 

中午吃什麼好?隨機選一個吧,好的,吃麵~

 

Random Sequence:隨機順序節點

 

節點介紹

 

這個也很好理解,就是順序節點的規則,但不是從左到右執行,而是隨機順序執行。

 

這個也很好理解,就是順序節點的規則,但不是從左到右執行,而是隨機順序執行。

當所有子節點都返回 Success時,它才會返回 Success。

 

當所有子節點都返回 Success時,它才會返回 Success。

 

當某個子節點返回 Failure 時,順序節點就會立刻返回 Failure。

 

當某個子節點返回 Failure 時,順序節點就會立刻返回 Failure。

 

新髮口訣

隨機順序節點,隨機順序,為真繼續,全真才真,一假即假,一假即停。

 

案例:番茄炒蛋

我現在要做一道番茄炒蛋,有的人先炒番茄,有的人先炒雞蛋,這裡我們就可以使用隨機順序節點了,如果炒雞蛋或者炒番茄失敗,那麼我們就吃不到番茄炒蛋了,只有兩個都成功了,才能吃到番茄炒蛋。
 

我現在要做一道番茄炒蛋,有的人先炒番茄,有的人先炒雞蛋,這裡我們就可以使用隨機順序節點了,如果炒雞蛋或者炒番茄失敗,那麼我們就吃不到番茄炒蛋了,只有兩個都成功了,才能吃到番茄炒蛋。

 

Parallel Complete:平行競爭節點

 

8.1、節點介紹

 

這個節點其實就是並行執行所有的子節點,只要有一個子節點回傳了結果,它就結束,並以這個子節點的結果為結果。

 

這個節點其實就是並行執行所有的子節點,只要有一個子節點回傳了結果,它就結束,並以這個子節點的結果為結果。

 

這個節點其實就是並行執行所有的子節點,只要有一個子節點回傳了結果,它就結束,並以這個子節點的結果為結果。

 

這個節點其實就是並行執行所有的子節點,只要有一個子節點回傳了結果,它就結束,並以這個子節點的結果為結果。

 

新髮口訣

並行競爭節點,並行執行,最速之子,以子為果。

 

Selector Evaluator:評估選擇節點

 

節點介紹

 

這個節點不是很好理解,它的邏輯是這樣的,從左到右順序執行,如果遇到子節點返回 Success,則立即結束,並返回 Success,否則繼續執行下一個子節點。

 

這個節點不是很好理解,它的邏輯是這樣的,從左到右順序執行,如果遇到子節點返回 Success,則立即結束,並返回 Success,否則繼續執行下一個子節點。

 

這個節點不是很好理解,它的邏輯是這樣的,從左到右順序執行,如果遇到子節點返回 Success,則立即結束,並返回 Success,否則繼續執行下一個子節點。

 

這個節點不是很好理解,它的邏輯是這樣的,從左到右順序執行,如果遇到子節點返回 Success,則立即結束,並返回 Success,否則繼續執行下一個子節點。

 

有同學會問了,那它跟 Selector 節點有啥差別

上面我用的是 Log 節點,會立即返回結果,如果是用Wait節點,則會有 Running 狀態,這個 Selector Evaluator 節點是個固執的強迫症節點,它認為子節點應該給它返回 Success,如果子節點返回了 Failure,它會硬著頭皮執行下一子節點,但是一旦下一個子節點處於 Running 狀態,它就會像個渣男一樣毫不猶豫地打斷並返回第一個子節點,重新執行,只要有機會它就想要一個 Success 結果,如果後續的子節點都是立即返回成功或失敗,而沒有 Running 狀態,則它會接受後續子節點的 Success,也就是說,它也不是非得第一個子節點不娶,後面的子節點只要立刻 Success,它就不打斷去重新找第一個子節點了,相當地渣男啊!

看,第二任只要考慮一下(Running 狀態),它就會立即打斷回去執行初戀。

 

看,第二任只要考慮一下(Running 狀態),它就會立即打斷回去執行初戀。

 

如果第二任立即答應了,它就會接受第二任的結果。

 

如果第二任立即答應了,它就會接受第二任的結果。

 

如果第二任直接給個 Failure,那麼這個渣男會去騷擾路人甲,如果路人甲給它 Success,它就會愛上路人甲。

 

如果第二任直接給個 Failure,那麼這個渣男會去騷擾路人甲,如果路人甲給它 Success,它就會愛上路人甲。

 

如果路人甲立刻給它 Failure,這個渣男才會死心。

 

如果路人甲立刻給它 Failure,這個渣男才會死心。

 

新髮口訣

評估選擇節點,渣男一個,從左到右,遇真即真,遇假繼續,Runing 時機打斷,從頭來過。

 

 

中斷

 

複合節點有中斷的權利,我們可以選取某個複合節點,然後點擊 Inspector,設定它的中斷模式。

 

複合節點有中斷的權利,我們可以選取某個複合節點,然後點擊 Inspector,設定它的中斷模式。

 

預設為 None,即無中斷,另外三個中斷模式,下文我會挨個進行示範。

這裡我先解釋一下什麼是中斷,像是你正在睡覺,突然地震了,這時候睡覺就要被中斷,執行逃跑的邏輯,命要緊。

複合節點的中斷控制是由誰來調度的呢?細心的同學應該會發現,執行行為樹的時候,會自動創建一個 Behavior Manager 對象,上面掛著 BehaviorManager 腳本,我們的行為樹的執行都是由這個 BehaviorManager 來調度的,它就是最高司令。

 

複合節點的中斷控制是由誰來調度的呢?細心的同學應該會發現,執行行為樹的時候,會自動創建一個 Behavior Manager 對象,上面掛著 BehaviorManager 腳本,我們的行為樹的執行都是由這個 BehaviorManager 來調度的,它就是最高司令。

 

有興趣的同學可以反編譯 BehaviorDesigner.Runtime.dll,查看 BehaviorManager 的來源碼。

 

有興趣的同學可以反編譯 BehaviorDesigner.Runtime.dll,查看 BehaviorManager 的來源碼。

 

Self 中斷:老媽喊你回家吃飯

一個複合節點下可以有多個子節點,假設現在有兩個子節點,假設此時正在執行第二個子節點(Running 狀態),突然來了一個事件,需要中斷第二個子節點,立即執行第一個子節點,這裡就可以使用Self中斷,Self 其實是站在複合節點的角度的,就是中斷複合節點自己。

假設你去朋友家打遊戲,你決定打完遊戲就回家,如果打遊戲過程中,老媽打電話喊你回家吃飯,那就中斷打遊戲乖乖回家,行為樹如下。
 

假設你去朋友家打遊戲,你決定打完遊戲就回家,如果打遊戲過程中,老媽打電話喊你回家吃飯,那就中斷打遊戲乖乖回家,行為樹如下。

 

沒有按下 A 鍵的執行效果如下,打完遊戲開開心心回家。

 

沒有按下 A 鍵的執行效果如下,打完遊戲開開心心回家。

 

打遊戲過程中,按下 A 鍵,中斷打遊戲,回家。

 

打遊戲過程中,按下 A 鍵,中斷打遊戲,回家。

 

Lower Priority 中斷:睡覺時地震

我們以睡覺的時候發生地震為例,示範 Lower Priority 中斷。 睡覺的時候如果發生地震,需要中斷睡覺,執行逃命邏輯。

 如下,睡覺節點與 Sequence 節點是平級關係,且睡覺節點在右邊,屬於低優先級,當正在執行睡覺節點時,左邊的 Sequence 節點想要中斷右邊的睡覺節點,設定 Lower Priority 中斷即可。

 

 如下,睡覺節點與 Sequence 節點是平級關係,且睡覺節點在右邊,屬於低優先級,當正在執行睡覺節點時,左邊的 Sequence 節點想要中斷右邊的睡覺節點,設定 Lower Priority 中斷即可。

 

我們從中斷的圖示也可以看出,它指向右邊,表示中斷右邊的節點的意思。

 

我們從中斷的圖示也可以看出,它指向右邊,表示中斷右邊的節點的意思。

 

Both 中斷:兩者都中斷

Both 中斷其實就是 Self 和 Lower Priority 都中斷,如下。

 

Both 中斷其實就是 Self 和 Lower Priority 都中斷,如下。

 

 

Variables:行為樹成員變數

 

我們點擊 Variables,可以為行為樹添加成員變量,也可以查看已新增的成員變量。

 

我們點擊 Variables,可以為行為樹添加成員變量,也可以查看已新增的成員變量。

 

新增變數

先起一個變數名,然後選擇變數的資料類型,我們也可以加入自訂的資料類型,需要進行變數類型拓展,下文會講解拓展變數類型的步驟,這裡我們先選一個 String 好了,最後點擊 Add 按鈕即可。

 

先起一個變數名,然後選擇變數的資料類型,我們也可以加入自訂的資料類型,需要進行變數類型拓展,下文會講解拓展變數類型的步驟,這裡我們先選一個 String 好了,最後點擊 Add 按鈕即可。

 

我們可以修改變數名,為變數設定初始值,如下。

 

我們可以修改變數名,為變數設定初始值,如下。

 

讀取變數

現在我們想透過 Log 節點把 myName 這個變數輸出出來。

先選取 Log 節點,切到 Inspector 頁,點選 Text 值最右邊的小點點,如下。

 

先選取 Log 節點,切到 Inspector 頁,點選 Text 值最右邊的小點點,如下。

 

 

此時會出現紅色的感嘆號。

 

此時會出現紅色的感嘆號。

 

我們點選下拉框,選取 myName 變數即可。

 

我們點選下拉框,選取 myName 變數即可。

 

我們運行行為樹,可以看到日誌輸出了變數值,如下。

 

我們運行行為樹,可以看到日誌輸出了變數值,如下。

 

修改變數

我們在 Log 節點左邊串一個 Set String 節點。

註:如果你的變數類型是 Bool,則這裡要使用 Set Bool 節點,其他類型同理,選擇對應的 Set 節點,如果是自訂的資料類型,則要自己拓展一個 Set 變數值的節點才行。

 

我們在 Log 節點左邊串一個 Set String 節點。

 

此時帶有一個紅色感嘆號,我們需要給它設定要修改的變量,如下。

 

此時帶有一個紅色感嘆號,我們需要給它設定要修改的變量,如下。

 

我們運行行為樹,可以看到輸出的變數值是皮皮貓了。

 

我們運行行為樹,可以看到輸出的變數值是皮皮貓了。

 

拓展變數類型

在實際專案中,我們大概率是要拓展行為樹的變數類型的,例如我現在有個 Blog 類。

 

/// <summary>

/// 博客

/// </summary>

public class Blog

{

   /// <summary>

   /// 作者

   /// </summary>

   public string author;

   

   /// <summary>

   /// 博客地址

   /// </summary>

   public string url;

   public override string ToString()

   {

       return $"author: {author}, url: {url}";

   }

}

 

我想讓他出現行為樹 Variables 的變數類型清單中,我們需要為它包裝一層 SharedBlog。

新建一個 SharedBlog 腳本。

 

新建一個 SharedBlog 腳本。

 

按照下面這個格式寫入即可:


namespace BehaviorDesigner.Runtime

{

   [System.Serializable]

   public class SharedT : SharedVariable<T>

   {

       public static implicit operator SharedT(T value)

       {

           return new SharedT { mValue = value };

       }

   }

}

 

SharedBlog 程式碼如下:

namespace BehaviorDesigner.Runtime

{

   [System.Serializable]

   public class SharedBlog : SharedVariable<Blog>

   {

       public static implicit operator SharedBlog(Blog value)

       {

           return new SharedBlog { mValue = value };

       }

   }

}
 

 

此時,我們就可以在變數類型清單中看到我們拓展的 Blog 變數類型了。

 

此時,我們就可以在變數類型清單中看到我們拓展的 Blog 變數類型了。

 

我們為行為樹新增一個 Blog 變數吧。

 

我們為行為樹新增一個 Blog 變數吧。

 

程式碼讀寫變數

上面我們拓展了一個 Blog 變數類型,並為行為樹添加了一個 Blog 變量,現在我們想在程式碼中對這個變數進行存取和修改,我們可以通過 BehaviorTree 的 GetVariable 方法和 SetVariable 方法。

 

public SharedVariable GetVariable(string name);

public void SetVariable(string name, SharedVariable item);

 

例:

 

// 獲取行為樹對象

var bt = GetComponent<BehaviorTree>();

// 訪問成員變量-----------------------------------------

var sharedBlog = (SharedBlog)bt.GetVariable("myBlog");

Debug.Log(sharedBlog.Value.ToString());

// 修改變量值-----------------------------------------

sharedBlog.Value.author = "Unity3D技術博主:林新發";

bt.SetVariable("myBlog", sharedBlog);


// 構建新的成員對象-----------------------------------------

SharedBlog newSharedBlog  = new SharedBlog();

Blog newBlog = new Blog();

newBlog.author = "博客技術專家:林新發";

newBlog.url = "https://blog.csdn.net/linxinfa";

newSharedBlog.SetValue(newBlog);

// 賦值成員變量

bt.SetVariable("myBlog", newSharedBlog);

 

 

行為樹事件

 

上文講 Sequence 節點的時候已經舉例講了行為樹事件,不過有些細節沒有講到,這裡我進行補充。 與事件相關的節點是 Send Event 和 Has Received Event。

 

上文講 Sequence 節點的時候已經舉例講了行為樹事件,不過有些細節沒有講到,這裡我進行補充。 與事件相關的節點是 Send Event 和 Has Received Event。

 

另外,我們也可以透過程式碼來發出事件和監聽事件,以下給大家示範一遍。


Send Event 節點

我們先看 Send Event 節點,可以在 Inspector 面板看到它的參數。

 

我們先看 Send Event 節點,可以在 Inspector 面板看到它的參數。

 

Target Game Object 參數

行為樹之間的事件是可以跨物體發送的,例如 A 物體上的行為樹會向 B 物體上的行為樹發送事件。

預設為 None,事件會發給自身的行為樹。

我們可以查看 SendEvent 節點的源碼,它呼叫了 GetDefaultGameObject 方法去取得目標物體。

 

我們可以查看 SendEvent 節點的源碼,它呼叫了 GetDefaultGameObject 方法去取得目標物體。

 

這個方法的源碼如下:

 

意思是如果為空,就回傳自身的 gameObject,也就是行為樹自身的物體。

 

意思是如果為空,就回傳自身的 gameObject,也就是行為樹自身的物體。 

如果我們想要設定這個 SendEvent 節點的 Target Game Object 參數,可以透過行為樹變數來傳遞,例如在 Variables 中定義一個 targetObj。

 

如果我們想要設定這個 SendEvent 節點的 Target Game Object 參數,可以透過行為樹變數來傳遞,例如在 Variables 中定義一個 targetObj。

 

然後 SendEvent 的 Target Game Object 引用這個 targetObj 變量。

 

然後 SendEvent 的 Target Game Object 引用這個 targetObj 變量。

 

而這個 targetObj 變數的賦值,我們可以透過程式碼來賦值,例如:

 

// go是目標物體GameObject對象,bt是自身行為樹對象

SharedGameObject targetObj = new SharedGameObject();

targetObj.Value = go;

bt.SetVariable("targetObj", targetObj);

 

Event Name 參數

Event Name 就是事件名稱,自己定義一個字串即可,建議為 XXX_EVENT。

 

Group 參數

 

這個 Group 參數又是乾啥用的呢?因為一個物體可以掛多個 BehaviorTree 元件,假設掛了 3 個 BehaviorTree 元件,我只想給其中的兩個 BehaviorTree 發送事件,這個時候就要用到 Group 了。

 

這個 Group 參數又是乾啥用的呢?因為一個物體可以掛多個 BehaviorTree 元件,假設掛了 3 個 BehaviorTree 元件,我只想給其中的兩個 BehaviorTree 發送事件,這個時候就要用到 Group 了。

我們可以在 BehaviorTree 元件上看到有一個 Group 參數。

 

我們可以在 BehaviorTree 元件上看到有一個 Group 參數。

 

我們可以給這些 BehaviorTree 分組,預設 Group 是 0 。

 

我們可以給這些 BehaviorTree 分組,預設 Group 是 0 。

 

如果 SendEvent 的 Group 也是 0,那麼這個物體下所有 Group 為 0 的 BehaviorTree 都會收到事件。

 

Argument 參數

 

我們可以看到有三個 Argument 參數,一般是用來做跨行為樹發送事件時的資料傳遞用的。

 

我們可以看到有三個 Argument 參數,一般是用來做跨行為樹發送事件時的資料傳遞用的。

例如 A 打了 B,B 收到被打事件,但它不知道是誰打它的,我們可以給它們定義一個 playerId 成員變量。

 

註:這裡你使用 GameObject 變數也可以,看具體需要~

 

註:這裡你使用 GameObject 變數也可以,看具體需要~

 

發事件的時候把 playerId 傳遞過去,B 收到事件後會去讀取這個參數,B 就知道 A 打了它了。

 

發事件的時候把 playerId 傳遞過去,B 收到事件後會去讀取這個參數,B 就知道 A 打了它了。

 

Has Receive Event 節點

Has Receive Event 節點參數如下。

 

Has Receive Event 節點參數如下。

 

Event Name 參數 

Event Name 參數就是要監聽的事件名稱,與 SendEvent 的 Event Name 要對應上。 

 

Stored Value 參數 

Stored Value 參數用來儲存傳遞過來的資料的,與 Send Event 的三個 Argument 順序對應。

注意,這裡是把傳遞過來的參數儲存到 Stored Value 設定的變數中,例如 A 行為樹傳遞了一個 playerId 過來,表示打人者的 Id,B 行為樹收到事件,把這個 plaeyrId 儲存到 fromPlayerId 變數中。

 

注意,這裡是把傳遞過來的參數儲存到 Stored Value 設定的變數中,例如 A 行為樹傳遞了一個 playerId 過來,表示打人者的 Id,B 行為樹收到事件,把這個 plaeyrId 儲存到 fromPlayerId 變數中。

 

然後我們可以在程式碼中通過 B 行為樹的 GetVariable 方法讀到這個 fromPlayerId。

 

var fromPlayerId = (SharedInt)bt.GetVariable("fromPlayerId");

Debug.Log($"{fromPlayerId} 打了我");

 

代碼中註冊及註銷事件

有時候我們需要在程式碼中自己註冊事件的回應函數,可以呼叫行為樹的 RegisterEvent 方法。

 

public void RegisterEvent<T, U, V>(string name, Action<T, U, V> handler);

public void RegisterEvent<T, U>(string name, Action<T, U> handler);

public void RegisterEvent<T>(string name, Action<T> handler);

public void RegisterEvent(string name, System.Action handler);

 

對應的,要註銷事件的回應函數,則呼叫 UnregisterEvent 方法。

 

public void UnregisterEvent<T, U, V>(string name, Action<T, U, V> handler);

public void UnregisterEvent<T, U>(string name, Action<T, U> handler);

public void UnregisterEvent<T>(string name, Action<T> handler);

public void UnregisterEvent(string name, System.Action handler);

 

可以查閱 Has Receive Event 節點的源碼。
 

可以查閱 Has Receive Event 節點的源碼。

 

 

拓展行為樹節點

 

繼承

在實際專案開發過程中,我們一般都需要自己拓展一些行為樹節點,我們知道,所有的節點都是繼承 Task 的,然後根據節點的功能分類,有細分了一些子類別出來,例如複合節點的繼承關係如下:

 

在實際專案開發過程中,我們一般都需要自己拓展一些行為樹節點,我們知道,所有的節點都是繼承 Task 的,然後根據節點的功能分類,有細分了一些子類別出來,例如複合節點的繼承關係如下:

 

我們想要封裝一個新的複合節點,也繼承 Composite 然後拓展即可。

 

我們想要封裝一個新的複合節點,也繼承 Composite 然後拓展即可。

 

同理,Action 類別的節點也如此。

 

同理,Action 類別的節點也如此。

 

我們可以參考 Log 節點、Wait 節點的寫法,自行拓展自己的 Action 節點。

 

案例:MoveTo

舉個例子,現在要寫一個移動主角到指定 Transform 位置的 Action,先建立一個 MoveTo 。

 

這樣,我們自己封裝的 MoveTo 節點就完成了。

 

引入 BehaviorDesigner 的命名空間,然後繼承 Action。

 

using UnityEngine;

using BehaviorDesigner.Runtime;

using BehaviorDesigner.Runtime.Tasks;

// 移動主角到指定Transform位置

public class MoveTo: Action

{

}

 

接著定義一些必要的 public 成員變量,這些變量會在 Inspector 。

 

using UnityEngine;

using BehaviorDesigner.Runtime;

using BehaviorDesigner.Runtime.Tasks;

// 移動主角到指定Transform位置

public class MoveTo : Action

{

  public float speed = 0;

  public SharedTransform target;

}
 

再接著,我們重寫 OnUpdate 方法,如下。


public override TaskStatus OnUpdate()

{

  if (Vector3.SqrMagnitude(transform.position - target.Value.position) < 0.1f) {

     return TaskStatus.Success;

  }

  transform.position = Vector3.MoveTowards(transform.position, target.Value.position, speed * Time.deltaTime);

  return TaskStatus.Running;

}

 

這樣,我們自己封裝的 MoveTo 節點就完成了。

 

這樣,我們自己封裝的 MoveTo 節點就完成了。

 

我們連個行為樹,讓 Cub 來回移動,效果如下。

 

我們連個行為樹,讓 Cub 來回移動,效果如下。

 

官方 Sample 包

Behavior Designer 官方自己寫了一些拓展包,我們可以把對應的包導入項目中使用。

 

Behavior Designer 官方自己寫了一些拓展包,我們可以把對應的包導入項目中使用。

 

這裡分享給大家

Behavior Designer 官方拓展包

 

 

範例補充

 

Behavior Designer 插件的基礎使用,前面已經做了詳細的介紹了,但是我發現例子很少,於是就有了後續這些內容,我自己琢磨實現一個簡單的 BOSS 的 AI 行為樹,把思路分享出來,各位開發者可以依據這些思路進行再擴展。

 

素材

 

素材

 

基礎使用

新建 2D 項目,搭建環境,主角和敵人 BOSS,給 BOSS 新增 animator 動畫,大致連接。

 

新建 2d 項目,搭建環境,主角和敵人 boss,給 boss 新增 animator 動畫,大致連接。

 

導入 Behavior Designer 插件,點擊菜單 Tools/Behavior Designer/Editor 即可打開編輯器窗口。

 

導入 BehaviorDesigner 插件,點擊菜單 Tools/Behavior Designer/Editor 即可打開編輯器窗口。

 

並在敵人身上建立行為樹,空格,新增 Repeater 節點,並勾選永遠循環。

 

並在敵人身上建立行為樹,空格,新增 Repeater 節點,並勾選永遠循環。

 

打印測試,sequence 節點控制從左到右執行。

 

打印測試,sequence 節點控制從左到右執行。

 

每 3 秒打印"打印日誌"。

 

每3秒打印"打印日誌"。

 

運行效果。

 

運行效果。

 

敵人物理攻擊

新增腳本 Attack。

 

using UnityEngine;

using BehaviorDesigner.Runtime;

using BehaviorDesigner.Runtime.Tasks;

public class Attack : Action

{

  public Animator animator;

  public GameObject player;
 

  public override void OnStart(){

      //切換動畫狀態為攻擊

      animator.SetTrigger("Attack");

  }

  public override void OnEnd(){

      Debug.Log("打印2");

  }

}

 

運轉效果,敵人每 3 秒發動一次攻擊。

 

運轉效果,敵人每 3 秒發動一次攻擊。


敵人面向玩家

新增 FacePlayer 腳本。

 

新增 FacePlayer 腳本。

using BehaviorDesigner.Runtime.Tasks;

using UnityEngine;

//始终面向主角

public class FacePlayer : Action

{

   private float baseScaleX;

   public GameObject player;

   public override void OnAwake()

   {

       baseScaleX = transform.localScale.x;

   }

   public override TaskStatus OnUpdate()

   {

       Vector3 scale = transform.localScale;

       scale.x = transform.position.x > player.transform.position.x ? baseScaleX : -baseScaleX;

       transform.localScale = scale;

       return TaskStatus.Success;

   }

}
 

運行效果,先朝向玩家再發動攻擊。

 

運行效果,先朝向玩家再發動攻擊。

 

敵人法術攻擊

新增 Cast 腳本。

 

using UnityEngine;

using BehaviorDesigner.Runtime.Tasks;

public class Cast : Action

{

  public GameObject player;

  public GameObject spell;

  public override void OnStart(){

      //生成技能攻擊特效

      float playerH = player.gameObject.GetComponent<SpriteRenderer>().sprite.bounds.size.y; //通過SpriteRenderer獲得人物高度

      Object.Instantiate(spell, player.transform.position + new Vector3(0, playerH, 0), Quaternion.identity);

  }

}

 

這次我們用 Set Trigger 節點控制動畫切換。

 

這次我們用 Set Trigger 節點控制動畫切換。

 

運行效果,大概流程就是開始等待 3 秒,面對主角,切換動畫為魔法攻擊動作,再等待 0.5 秒後切換回 Idle 動畫,並運行 Cast 代碼,觸發攻擊特效,一直循環。

 

運行效果,大概流程就是開始等待3秒,面對主角,切換動畫為魔法攻擊動作,再等待 0.5 秒後切換回 Idle 動畫,並運行 Cast 代碼,觸發攻擊特效,一直循環。

 

隨機進行攻擊

關鍵就是 Random Selector 節點的使用。

中間插入 Random Selector 節點,分別連接兩種攻擊模式,運行效果。

 

中間插入 Random Selector 節點,分別連接兩種攻擊模式,運行效果。

 

敵人不同的階段

你可能也會希望 BOSS 在不同階段有不同的效果,例如半血以下狂暴,不同技能等。

新增 IsHealthUnder 腳本,我在這裡簡單舉個例子。

 

using BehaviorDesigner.Runtime.Tasks;

public class IsHealthUnder : Action

{

   public float health;

   public override TaskStatus OnUpdate()

   {

       return health < 50 ? TaskStatus.Success : TaskStatus.Failure;

   }

}
 

新增 Selector 節點。

 

新增 Selector 節點。

 

運行效果,因為是測試,我這裡就手動改敵人的血量了。

當血量低於 50 時,處於第二階段,就會走左邊,打印日誌,你可以在這裡加入敵人新的狀態和技能,或者過場動畫。

 

當血量低於 50 時,處於第二階段,就會走左邊,打印日誌,你可以在這裡加入敵人新的狀態和技能,或者過場動畫。

 

當血量大於 100 時,處於第一階段,敵人還是正常走前面的邏輯。

 

當血量大於 100 時,處於第一階段,敵人還是正常走前面的邏輯。

 

 

Behavior Designer 相關教學影片

 

如果還是不懂的小夥伴,這邊推薦幾部影片,大家可以自行去學習!

 

 

 

 

 

AI 行動大師插件下載點

 

Behavior Designer

Asset Store下載連結:Behavior Designer

Behavior Designer 官方拓展包 Google 下載連結:本載點文件僅供學術交流,請勿用於商業用途

Behavior Designer 官方線上文件

Behavior Designer 官方網站

————————————————

以上內容改編節錄 CSDN 作者:林新發向宇it

 

更多好用插件:【Unity 好用插件推薦】持續更新,一起讓遊戲開發事半功倍!

 

 

 

本文原創(或整理)於亞洲電玩通,未經作者與本站同意不得隨意引用、轉載、改編或截錄。

特約作家簡介

X
A
Y
B
JamXu的頭像
JamXu
十年遊戲研發
二十年遊戲台主
三十年遊戲玩家

經中華網龍遊戲企劃進入遊戲圈,然後被雷打到去學程式前後端又學了點設計帶帶幾個研發團隊,見證了 3D 渲染技術及遊戲引擎互相進步,也見證了研發代理的更迭與博弈遊戲的興起,再毅然研究起 SEO 網路行銷社群廣告投放,深信自研自賣才是最大贏家,期望能為台灣研發重回輝煌時光貢獻一點力量。如果你也有遊戲夢,歡迎交流認識。


支持贊助 / DONATE

 

亞洲電玩通只是很小的力量,但仍希望為復甦台灣遊戲研發貢獻一點動能,如果您喜歡亞洲電玩通的文章,或是覺得它們對您有幫助,歡迎給予一些支持鼓勵,不論是按讚追蹤或是贊助,讓亞洲電玩通持續產出,感謝。

亞洲電玩通AsiaGameMaster - Steam 遊戲鑑賞家
亞洲電玩通AsiaGameMaster - FB 粉絲專頁
亞洲電玩通AsiaGameMaster - IG 粉絲專頁
亞洲電玩通AsiaGameMaster - Twitter
亞洲電玩通AsiaGameMaster - Yoytube 粉絲專頁
亞洲電玩通AsiaGameMaster - Tiktok

BTC

亞洲電玩通AsiaGameMaster - BTC 鏈贊助地址

352Bw8r46rfXv6jno8qt9Bc3xx6ptTcPze

 

ETH

亞洲電玩通AsiaGameMaster - ETH 鏈贊助地址

0x795442E321a953363a442C76d39f3fbf9b6bC666

 

TRON

亞洲電玩通AsiaGameMaster - TRON 鏈贊助地址

TCNcVmin18LbnXfdWZsY5pzcFvYe1MoD6f

延伸閱讀