Behaviour Tree(ビヘイビアーツリー)

確認済のバージョン: 2017.3

-

難易度: 初級

(注)これはスクリプト限定のシステムです。この機能および使用方法を理解するには、スクリプトの基礎知識と、Unity で C# が機能する仕組みの理解が必要です。

Behaviour Trees は、その名の示す通り、挙動(behaviour)をアクションのツリーを使って記述する方法です。Game Kit では敵の AI の挙動やボス戦闘のシーケンスの制御に使用されています。

以下は、Behaviour Tree を視覚的に示した例です。

理論

ゲームの毎回の更新中に、ツリーが「チェック」されます。つまりルートのすべての子ノードが一通りチェックされます。そのノードに子がある場合などは更に深くチェックされます。

各ノードにはそれに関連付けられたアクションがあり、それぞれが 3 つのステートのうち 1 つをその親に戻します。

  • Success ― ノードがそのタスクを正常に完了した場合です。

  • Failure ― ノードがタスクに失敗した場合です。

  • Continue ― ノードのタスクが未完了の場合です。

戻されたステートの使われ方は、ノードの親ごとに異なります。

(例)

  • Selector は、現在の子が Failure または Success を返した場合は次の子をアクティブにし、Continue を返した場合は現在の子をアクティブに保ちます。

  • Test ノードは、テストが true だった場合はその子ノードを呼び出して子ステートを戻します。テストが false だった場合は子ノードを呼び出さずに Failure を戻します。

Game Kit における実装

Game Kit 内では、Behaviour Tree はスクリプトを通して使用されています。以下はごく単純な Behaviour Tree の例です。

まずファイルのトップに using BTAI; を追加する必要があります。

Code snippet

Root aiRoot = BT.Root();

aiRoot.Do (
    BT.If(TestVisibleTarget).Do (
        BT.Call(Aim),
        BT.Call(Shoot)
    ),
    BT.Sequence().Do (
        BT.Call(Walk),
        BT.Wait(5.0f),
        BT.Call(Turn),
        BT.Wait(1.0f),
        BT.Call(Turn)
    )
);

aiRoot はクラス内にメンバーとして保存します。これは、Tree アクションを実行可能にするために Update 関数内で aiRoot.Tick() を呼び出す必要があるためです。

UpdateaiRoot.Tick() 内でどのように機能するか順を追って見てみましょう。

  • まず、関数「TestVisibleTarget」が true を戻すかどうかテストします。true を戻す場合は続けて子が実行されます。子は関数「Aim」と「Shoot」を呼び出しています。

  • テストが false を戻した場合、If ノードは Failure を戻し、続けてルートは次の子へと進みます。これは 1 つのシーケンスであり、その最初の子の実行によって開始されます。

    • これによって関数「Walk」が呼び出されます。この関数は Success を戻すことで、このシーケンスが次の子をアクティブに設定して実行します。

    • Wait ノードが実行されます。5 秒間の待機が必要ですが、1 回目の呼び出しが行われた所であるため、まだ待機時間が満たされておらず、したがって Continue が戻されます。

    • このシーケンスは、そのアクティブな子から Continue ステートを受け取るため、アクティブな子が変更されません。そのため、次の Update では同じ子から開始されます。

  • Wait ノードは、十分に更新されて待機時間が経つと Success を戻し、その結果シーケンスが次の子に進みます。

ノードリスト

Sequence

子ノードをひとつずつ実行します。子の戻すステートによって挙動が以下のように変わります。

  • Success ― シーケンスは次のフレームで次の子をチェックします。

  • Failure ― シーケンスは次のフレームで最初の子に戻ります。

  • Continue ― シーケンスは次のフレームで同じノードを再び呼び出します。

RandomSequence

呼び出される度に、そのリストからランダムな子を実行します。コンストラクター内で、それぞれの子に適用する重要度のリストを整数配列として指定し、特定の子を選択されやすくすることも可能です。

Selector

子のどれかが Success を戻すまですべての子を順番に実行し、子のどれかが Success を戻した時点で、残りの子ノードは実行せずに終了します。どの子も Success を戻さなかった場合は、このノードは Failure を戻します。

Call

該当の関数を呼び出します。この関数は常に Success を戻します。

If

該当の関数を呼び出します。

  • true が戻された場合は、現在アクティブな子を呼び出してそのステートを戻します。

  • それ以外の場合は、子を呼び出すことなく Failure を戻します。

While

その関数が true を戻す限り Continue を戻します(したがって、次のフレームでツリーがチェックする時は、以前のノードのすべてをチェックするのではなく、同じノードから再開します)。

子が 1 つずつ実行されます。

関数が false を戻した場合に Failure を戻します。

Condition

このノードは、関数が true を戻すと Success を戻し、false の場合は Failure を戻します。

自身の子の戻り値に依存する他のノード([例]Sequence や Selector)と連結されている場合に役立ちます。

Repeat

すべての子ノードを、設定回数、繰り返し実行します。

設定回数に達するまで Continue を戻し続け、回数に達すると Success を戻します。

Wait

(初回呼び出しから数えて)設定回数に達するまで Continue を戻し、回数に達すると Success を戻します。

Trigger

トリガーの設定(または、最後の引数が false に設定されている場合は、トリガーの設定解除)を、該当アニメーター内で行えるようにします。常に Success を戻します。

SetBool

該当アニメーター内にブールパラメーターを設定できます。常に Success を戻します。

SetActive 該当ゲームオブジェクトの有効・無効を設定します。常に Success を戻します。