1. 程式人生 > 實用技巧 >行為樹(三)BT的佇列節點

行為樹(三)BT的佇列節點

Sequences(佇列)

只要序列的所有子代返回SUCCESS,它便會對其進行Tick

如果有任何子級返回FAILURE,則序列中止。

當前,該框架提供三種節點:

  1. Sequence
  2. SequenceStar
  3. ReactiveSequence

它們具有以下規則:

  • tick第一個節點之前,節點狀態為RUNNING
  • 如果一個節點返回成功SUCCESS,將會tick下一個節點。
  • 如果最後一個節點也返回SUCCESS,所有的節點被暫停,並且序列返回SUCCESS

要了解三個ControlNode有何不同,請參考下表:

Type of ControlNode Child returns FAILURE Child returns RUNNING
Sequence Restart Tick again
ReactiveSequence Restart Restart
SequenceStar Tick again Tick again

“Restart”是指從列表的第一個子級開始重新啟動整個序列。

“Tick again”是指下次對序列進行Tick時,將再次對同一個孩子進行Tick。 已經返回SUCCESS的先前的同級項不再被打勾。

Sequence

該樹表示計算機遊戲中狙擊手的行為。

status = RUNNING;
// _index is a private member

while(_index < number_of_children)
{
    child_status = child[_index]->tick();

    if( child_status == SUCCESS ) {
        _index++;
    }
    else if( child_status == RUNNING ) {
        // keep same index
        return RUNNING;
    }
    else if( child_status == FAILURE ) {
        HaltAllChildren();
        _index = 0;
        return FAILURE;
    }
}
// all the children returned success. Return SUCCESS too.
HaltAllChildren();
_index = 0;
return SUCCESS;

ReactiveSequence

該節點對於連續檢查條件特別有用;但是使用者在使用非同步子級時也應小心,確保它們不會被tick的頻率超過預期。

ApproachEnemy是一個非同步操作,返回RUNNING直到最終完成。

條件isEnemyVisible將被呼叫很多次,並且如果條件為False(即“失敗”),則ApproachEnemy被暫停。

status = RUNNING;

for (int index=0; index < number_of_children; index++)
{
    child_status = child[index]->tick();

    if( child_status == RUNNING ) {
        return RUNNING;
    }
    else if( child_status == FAILURE ) {
        HaltAllChildren();
        return FAILURE;
    }
}
// all the children returned success. Return SUCCESS too.
HaltAllChildren();
return SUCCESS;

SequenceStar

當您不想再次tick已經返回SUCCESS的子節點時,請使用此ControlNode:SequenceStar

範例:

這是巡邏代理/機器人,只能訪問位置A,B和C一次。如果動作GoTo(B)失敗,GoTo(A)將不再被勾選。

另一方面,必須在每個刻度上都檢查isBatteryOK,因此其父級必須為ReactiveSequence

status = RUNNING;
// _index is a private member

while( index < number_of_children)
{
    child_status = child[index]->tick();

    if( child_status == SUCCESS ) {
        _index++;
    }
    else if( child_status == RUNNING || 
             child_status == FAILURE ) 
    {
        // keep same index
        return child_status;
    }
}
// all the children returned success. Return SUCCESS too.
HaltAllChildren();
_index = 0;
return SUCCESS;

程式碼均為虛擬碼

原文