Unity3D項目的行為樹。以代碼驅動的方法編寫,以最大限度地利用建築商模式對大型項目的可維護性。靈感來自流利的行為樹。
特徵
支持
如果您有疑問或需要幫助,請加入Discord社區。
請參閱Trello Board的即將到來的功能和發展進度。
創建樹時,您需要將它們存儲在變量中以正確緩存所有必要的數據。
using UnityEngine ;
using CleverCrow . Fluid . BTs . Tasks ;
using CleverCrow . Fluid . BTs . Trees ;
public class MyCustomAi : MonoBehaviour {
[ SerializeField ]
private BehaviorTree _tree ;
private void Awake ( ) {
_tree = new BehaviorTreeBuilder ( gameObject )
. Sequence ( )
. Condition ( " Custom Condition " , ( ) => {
return true ;
} )
. Do ( " Custom Action " , ( ) => {
return TaskStatus . Success ;
} )
. End ( )
. Build ( ) ;
}
private void Update ( ) {
// Update our tree every frame
_tree . Tick ( ) ;
}
}
根據您返回的任務狀態的不同,將會發生不同的事情。
tree.Tick()
運行tree.Tick()
。樹由樹跟踪指針參考,只有在調用tree.Reset()
時才能清除。只要您的樹存儲變量設置為public
或具有SerializeField
屬性屬性。在編輯器中運行遊戲時,您將能夠打印樹的可視化。請注意,遊戲不運行時無法查看樹。由於必須建造樹才能可視化。
您可以用幾行安全地將新代碼添加到行為樹中。允許您在支持未來版本升級的同時自定義BTS。
using UnityEngine ;
using CleverCrow . Fluid . BTs . Tasks ;
using CleverCrow . Fluid . BTs . Tasks . Actions ;
using CleverCrow . Fluid . BTs . Trees ;
public class CustomAction : ActionBase {
protected override TaskStatus OnUpdate ( ) {
Debug . Log ( Owner . name ) ;
return TaskStatus . Success ;
}
}
public static class BehaviorTreeBuilderExtensions {
public static BehaviorTreeBuilder CustomAction ( this BehaviorTreeBuilder builder , string name = " My Action " ) {
return builder . AddNode ( new CustomAction { Name = name } ) ;
}
}
public class ExampleUsage : MonoBehaviour {
public void Awake ( ) {
var bt = new BehaviorTreeBuilder ( gameObject )
. Sequence ( )
. CustomAction ( )
. End ( ) ;
}
}
流體行為樹通過Unity的軟件包管理器使用。為了使用它,您需要將以下行添加到Packages/manifest.json
文件中。之後,您將能夠視覺控制您在Unity的包裝管理器窗口中使用哪種特定版本的流體行為樹。必須這樣做,以便您的Unity編輯器可以連接到NPM的軟件包註冊表。
{
"scopedRegistries" : [
{
"name" : " NPM " ,
"url" : " https://registry.npmjs.org " ,
"scopes" : [
" com.fluid "
]
}
],
"dependencies" : {
"com.fluid.behavior-tree" : " 2.2.0 "
}
}
特定版本和發行說明的檔案可在“版本”頁面上找到。
您可能想查看捕獲的標誌示例項目,以示出如何在項目中使用流體行為樹。它展示了試圖捕獲國旗的單位的實時使用,同時抓住了力量,以嘗試獲得上風。
您可能想查看捕獲的標誌示例項目,以示出如何在項目中使用流體行為樹。它展示了試圖捕獲國旗的單位的實時使用,同時抓住了力量,以嘗試獲得上風。
流體行為樹帶有強大的預製動作,條件,複合材料和其他節點的庫,以幫助加快開發過程。
您可以即時創建通用動作。如果您發現自己重複使用相同的動作,則可能需要研究有關編寫自己的自定義操作的部分。
. Sequence ( )
. Do ( " Custom Action " , ( ) => {
return TaskStatus . Success ;
} )
. End ( )
在行為樹上跳過許多壁蝨。
. Sequence ( )
// Wait for 1 tick on the tree before continuing
. Wait ( 1 )
. Do ( MyAction )
. End ( )
等待,直到傳遞的秒數已在deltaTime
到期。
. Sequence ( )
. WaitTime ( 2.5f )
. Do ( MyAction )
. End ( )
您可以即時創建通用條件。如果您發現自己重複使用相同的動作,則可能需要研究編寫自己的自定義條件的部分。
. Sequence ( )
. Condition ( " Custom Condtion " , ( ) => {
return true ;
} )
. Do ( MyAction )
. End ( )
根據傳遞的機會,隨機評估節點為真或錯誤。
. Sequence ( )
// 50% chance this will return success
. RandomChance ( 1 , 2 )
. Do ( MyAction )
. End ( )
按順序運行每個子節點,並期望成功的狀態可以打勾下一個節點。如果返回失敗,則該序列將停止執行子節點並將失敗返回給父母。
請注意,重要的是,每個複合材料之後是.End()
語句。這可以確保在樹上建造樹時正確嵌套您的節點。
. Sequence ( )
. Do ( ( ) => { return TaskStatus . Success ; } )
. Do ( ( ) => { return TaskStatus . Success ; } )
// All tasks after this will not run and the sequence will exit
. Do ( ( ) => { return TaskStatus . Failure ; } )
. Do ( ( ) => { return TaskStatus . Success ; } )
. End ( )
運行每個孩子節點直到返回成功。
. Selector ( )
// Runs but fails
. Do ( ( ) => { return TaskStatus . Failure ; } )
// Will stop here since the node returns success
. Do ( ( ) => { return TaskStatus . Success ; } )
// Does not run
. Do ( ( ) => { return TaskStatus . Success ; } )
. End ( )
隨機選擇帶有洗牌算法的子節點。看起來直到返回Success
或每個節點失敗為止。每當樹最初開始運行它時,都會隨時隨地。
. SelectorRandom ( )
. Do ( ( ) => { return TaskStatus . Failure ; } )
. Do ( ( ) => { return TaskStatus . Success ; } )
. Do ( ( ) => { return TaskStatus . Failure ; } )
. End ( )
同時運行所有子節點,直到他們都回來成功。退出並停止所有運行節點,如果其中任何一個返回失敗。
. Parallel ( )
// Both of these tasks will run every frame
. Do ( ( ) => { return TaskStatus . Continue ; } )
. Do ( ( ) => { return TaskStatus . Continue ; } )
. End ( )
裝飾器是包裝任何節點以更改返回值(或執行特殊邏輯)的母元素。它們非常強大,對動作,條件和復合材料非常有利。
您可以用自己的自定義裝飾器代碼包裝任何節點。這使您可以自定義可重複使用的功能。
注意:您必須在子節點上手動調用Update()
,否則不會發射。另外,每個裝飾符都必須隨後進行.End()
語句。否則,樹將無法正確構建。
. Sequence ( )
. Decorator ( " Return Success " , child => {
child . Update ( ) ;
return TaskStatus . Success ;
} )
. Do ( ( ) => { return TaskStatus . Failure ; } )
. End ( )
. Do ( ( ) => { return TaskStatus . Success ; } )
. End ( )
如果是TaskStatus.Success
或TaskStatus.Failure
,則將返回的子節點的返回狀態逆轉。不更改TaskStatus.Continue
。
. Sequence ( )
. Inverter ( )
. Do ( ( ) => { return TaskStatus . Success ; } )
. End ( )
. End ( )
如果孩子返回TaskStatus.Success
,請返回TaskStatus.Failure
。不更改TaskStatus.Continue
。
. Sequence ( )
. ReturnSuccess ( )
. Do ( ( ) => { return TaskStatus . Failure ; } )
. End ( )
. End ( )
如果孩子返回TaskStatus.Failure
,請返回TaskStatus.Success
。不更改TaskStatus.Continue
。
. Sequence ( )
. ReturnFailure ( )
. Do ( ( ) => { return TaskStatus . Success ; } )
. End ( )
. End ( )
返回TaskStatus.Continue
,無論孩子返回什麼狀態。該裝飾器(以及所有後代任務)可以通過呼叫BehaviorTree.Reset()
中斷。
. Sequence ( )
. RepeatForever ( )
. Do ( ( ) => { return TaskStatus . Success ; } )
. End ( )
. End ( )
返回TaskStatus.Failure
如果孩子返回TaskStatus.Failure
,否則返回TaskStatus.Continue
。
. Sequence ( )
. RepeatUntilFailure ( )
. Do ( ( ) => { return TaskStatus . Success ; } )
. End ( )
. End ( )
返回TaskStatus.Success
如果孩子返回TaskStatus.Success
,否則它將返回TaskStatus.Continue
。
. Sequence ( )
. RepeatUntilSuccess ( )
. Do ( ( ) => { return TaskStatus . Success ; } )
. End ( )
. End ( )
樹只能與幾行代碼結合使用。這使您可以創建可注射的行為樹,這些樹將不同的節點捆綁在一起,以獲得複雜功能,例如搜索或攻擊。
請注意,剪接的樹需要一棵新建的樹進行注射,因為節點僅在.Build()
上深處複製。
using CleverCrow . Fluid . BTs . Trees ;
using CleverCrow . Fluid . BTs . Tasks ;
using UnityEngine ;
public class MyCustomAi : MonoBehaviour {
private BehaviorTree _tree ;
private void Awake ( ) {
var injectTree = new BehaviorTreeBuilder ( gameObject )
. Sequence ( )
. Do ( " Custom Action " , ( ) => {
return TaskStatus . Success ;
} )
. End ( ) ;
_tree = new BehaviorTreeBuilder ( gameObject )
. Sequence ( )
. Splice ( injectTree . Build ( ) )
. Do ( " Custom Action " , ( ) => {
return TaskStatus . Success ;
} )
. End ( )
. Build ( ) ;
}
private void Update ( ) {
// Update our tree every frame
_tree . Tick ( ) ;
}
}
使流體行為樹如此強大的原因是能夠編寫自己的節點並將其添加到構建器中而無需編輯任何來源。您甚至可以創建添加新構建器功能的Unity軟件包。例如,我們可以編寫一個新的樹木建築商方法,該方法僅使用幾行代碼來設置AI系統的目標。
var tree = new BehaviorTreeBuilder ( gameObject )
. Sequence ( )
. AgentDestination ( " Find Enemy " , target )
. Do ( ( ) => {
// Activate chase enemy code
return TaskStatus . Success ;
} )
. End ( )
. Build ( ) ;
創建您的第一個自定義操作並實施大約需要3分鐘。首先創建一個新動作。
using CleverCrow . Fluid . BTs . Tasks ;
using CleverCrow . Fluid . BTs . Tasks . Actions ;
using UnityEngine ;
using UnityEngine . AI ;
public class AgentDestination : ActionBase {
private NavMeshAgent _agent ;
public Transform target ;
protected override void OnInit ( ) {
_agent = Owner . GetComponent < NavMeshAgent > ( ) ;
}
protected override TaskStatus OnUpdate ( ) {
_agent . SetDestination ( target . position ) ;
return TaskStatus . Success ;
}
}
接下來,我們需要使用我們的新代理操作擴展BehaviorTreeBuilder
腳本。有關C#類擴展的更多信息,請參見官方文檔。
using CleverCrow . Fluid . BTs . Trees ;
public static class BehaviorTreeBuilderExtensions {
public static BehaviorTreeBuilder AgentDestination ( this BehaviorTreeBuilder builder , string name , Transform target ) {
return builder . AddNode ( new AgentDestination {
Name = name ,
target = target ,
} ) ;
}
}
你完成了!現在,您已經創建了一個自定義操作和可擴展的行為樹建造器,該製造商將來對新版本進行了證明。以下示例將更加相同。但是每個都涵蓋了不同的節點類型。
您可以使用以下模板創建自己的自定義操作。這對於捆綁您不斷使用的代碼很有用。
using UnityEngine ;
using CleverCrow . Fluid . BTs . Tasks ;
using CleverCrow . Fluid . BTs . Tasks . Actions ;
public class CustomAction : ActionBase {
// Triggers only the first time this node is run (great for caching data)
protected override void OnInit ( ) {
}
// Triggers every time this node starts running. Does not trigger if TaskStatus.Continue was last returned by this node
protected override void OnStart ( ) {
}
// Triggers every time `Tick()` is called on the tree and this node is run
protected override TaskStatus OnUpdate ( ) {
// Points to the GameObject of whoever owns the behavior tree
Debug . Log ( Owner . name ) ;
return TaskStatus . Success ;
}
// Triggers whenever this node exits after running
protected override void OnExit ( ) {
}
}
將您的新節點添加到擴展名中。
using CleverCrow . Fluid . BTs . Trees ;
public static class BehaviorTreeBuilderExtensions {
public static BehaviorTreeBuilder CustomAction ( this BehaviorTreeBuilder builder , string name = " My Action " ) {
return builder . AddNode ( new CustomAction {
Name = name ,
} ) ;
}
}
可以使用以下示例模板添加自定義條件。如果AI可以移動到位置以及其他需要復雜檢查的任務,您將需要使用這些檢查,例如視力。
using UnityEngine ;
using CleverCrow . Fluid . BTs . Tasks ;
public class CustomCondition : ConditionBase {
// Triggers only the first time this node is run (great for caching data)
protected override void OnInit ( ) {
}
// Triggers every time this node starts running. Does not trigger if TaskStatus.Continue was last returned by this node
protected override void OnStart ( ) {
}
// Triggers every time `Tick()` is called on the tree and this node is run
protected override bool OnUpdate ( ) {
// Points to the GameObject of whoever owns the behavior tree
Debug . Log ( Owner . name ) ;
return true ;
}
// Triggers whenever this node exits after running
protected override void OnExit ( ) {
}
}
將新條件添加到您的行為樹建造器中,並在以下片段中添加。
using CleverCrow . Fluid . BTs . Trees ;
public static class BehaviorTreeBuilderExtensions {
public static BehaviorTreeBuilder CustomCondition ( this BehaviorTreeBuilder builder , string name = " My Condition " ) {
return builder . AddNode ( new CustomCondition {
Name = name ,
} ) ;
}
}
流體行為樹不僅限於自定義動作和條件。您可以使用相當簡單的API創建新的複合類型。這是基本序列的示例。
using CleverCrow . Fluid . BTs . TaskParents . Composites ;
using CleverCrow . Fluid . BTs . Tasks ;
public class CustomSequence : CompositeBase {
protected override TaskStatus OnUpdate ( ) {
for ( var i = ChildIndex ; i < Children . Count ; i ++ ) {
var child = Children [ ChildIndex ] ;
var status = child . Update ( ) ;
if ( status != TaskStatus . Success ) {
return status ;
}
ChildIndex ++ ;
}
return TaskStatus . Success ;
}
}
將自定義復合材料添加到行為樹中與添加動作一樣簡單。只需採用一行代碼即可。
using CleverCrow . Fluid . BTs . Trees ;
public static class BehaviorTreeBuilderExtensions {
public static BehaviorTreeBuilder CustomSequence ( this BehaviorTreeBuilder builder , string name = " My Sequence " ) {
return builder . ParentTask < CustomSequence > ( name ) ;
}
}
還可以定制裝飾器來減少重複代碼。
using CleverCrow . Fluid . BTs . Decorators ;
using CleverCrow . Fluid . BTs . Tasks ;
public class CustomInverter : DecoratorBase {
protected override TaskStatus OnUpdate ( ) {
if ( Child == null ) {
return TaskStatus . Success ;
}
var childStatus = Child . Update ( ) ;
var status = childStatus ;
switch ( childStatus ) {
case TaskStatus . Success :
status = TaskStatus . Failure ;
break ;
case TaskStatus . Failure :
status = TaskStatus . Success ;
break ;
}
return status ;
}
}
實施裝飾器類似於復合材料。如果您需要在復合材料上設置參數,則需要在Method BehaviorTreeBuilder.AddNodeWithPointer()
上進行戰利品。
using CleverCrow . Fluid . BTs . Trees ;
public static class BehaviorTreeBuilderExtensions {
public static BehaviorTreeBuilder CustomInverter ( this BehaviorTreeBuilder builder , string name = " My Inverter " ) {
// See BehaviorTreeBuilder.AddNodeWithPointer() if you need to set custom composite data from arguments
return builder . ParentTask < CustomInverter > ( name ) ;
}
}
如果您使用的是自動格式化器,則可能會使用構建器語法來處理您的代碼格式。為了避免這種情況,您可以在Jetbrains Rider中關閉格式。如果您需要特定的IDE,則不難搜索您需要的特定格式禁用評論。
// @formatter:off
_tree = new BehaviorTreeBuilder ( gameObject )
. Sequence ( )
. Condition ( " Custom Condition " , ( ) => {
return true ;
} )
. Do ( " Custom Action " , ( ) => {
return TaskStatus . Success ;
} )
. End ( )
. Build ( ) ;
// @formatter:on
要訪問“包裹經理”友好的夜間開發develop
,您需要手動編輯Packages/manifest.json
。
{
"dependencies" : {
"com.fluid.behavior-tree" : " https://github.com/ashblue/fluid-behavior-tree.git#nightly "
}
}
請注意,要獲得較新的夜間構建,您必須刪除這一行和清單中的任何相關鎖定數據,讓Unity重建,然後將其添加回。當Unity鎖定git URL的提交哈希作為軟件包。
如果您想運行開發環境,則需要安裝Node.js。然後一次從根中運行以下內容。
npm install
如果您想從根部創建構建運行npm run build
,它將填充dist
文件夾。
所有提交都應使用commitizen(運行npm install
時自動安裝)進行。發行時將提交自動編譯為版本號,因此非常重要。沒有基於犯罪的提交的PR將被拒絕。
將提交類型從根部從根部開始到終端
npm run commit
請參閱貢獻指南文件以獲取更多信息。
謝謝這些好人(表情符號鑰匙):
灰藍 | 傑西·塔拉維拉·格林伯格(Jesse Talavera-Greenberg) | 純化的生產 ? | 馬丁·杜弗利(Martin Duvergey) ? | 呼叫堆 ? | piotr jastrzebski | Sounghoo |
tnthomas ? | Ownez | angstr0m ? | Izzy ? | 傑里米萬克 |
該項目遵循全企業規範。歡迎任何形式的貢獻!
謝謝這些好人(表情符號鑰匙):
該項目遵循全企業規範。歡迎任何形式的貢獻!