【Unity】Behavior Designerにおける更新処理の制御とTaskの処理タイミングについて

Behavior Designerの更新処理の制御とTaskの処理タイミングについてまとめました。

Unity2018.3.9

はじめに

Behavior Designerは初期設定では更新タイミングはUnityのUpdateに従い、
同じTaskの繰り返しは同フレームで行われなかったりします。

厳密にAIを制御するにはこのあたりの処理フローを理解・制御しないといけません。
そのためこの記事では更新処理の制御とTaskの処理タイミングについてまとめます。

更新処理はBehavior Managerが行う

Behavior Treeをランタイムで実行すると、Behavior Managerというオブジェクトが自動的に作られるのがわかります。

f:id:halya_11:20190331190140p:plain

これはすべてのBehavior Treeの更新処理を行うオブジェクトで、
InspectorにはBehavior Managerというコンポーネントがアタッチされていることがわかります。

f:id:halya_11:20190331190250p:plain

更新処理を制御する

Behavior Managerによる更新処理を制御するには、まずシーンにBehavior ManagerのアタッチされたGameObjectを配置します。
これでBehavior Treeの更新にこのBehavior Managerが使用されるようになります。

更新処理を一定間隔で行いたい場合、Behavior ManagerのUpdate IntervalをSpecify Secondsに設定します。
そしてSecondsフィールドに更新間隔の秒数を指定します。

f:id:halya_11:20190331190620p:plain

また、手動で更新を行う場合にはBehavior ManagerのUpdate IntervalをManualにします。

f:id:halya_11:20190331191046p:plain

その上でスクリプトからBehaviorManager.Tick()を呼ぶことで更新します。

using BehaviorDesigner.Runtime;
using UnityEngine;

public class BehaviorManagerController : MonoBehaviour
{
    [SerializeField]
    private BehaviorManager _manager;

    [SerializeField]
    private bool _isActive = true;

    private void Update()
    {
        if (!_isActive) {
            return;
        }
        // BehaviorManagerを更新する
        _manager.Tick();
    }
}

Tickの引数にBehavior Treeを与えれば特定のBehavior Treeだけを更新することもできます。

BehaviorManager manager;
BehaviorTree tree;
manager.Tick(tree);

1フレーム内で処理するTaskを制御する

初期設定では、Taskが成功/失敗すると同フレーム内で次のTaskを処理します。
つまり下記のようなツリーの場合、同じフレームですべてのTaskが処理されます。

f:id:halya_11:20190331201238p:plain

もしあるTaskの処理が完了した時にそれ以降のTaskの処理を次のフレームに回したければ、
TaskのInspectorのInstantのチェックを外します。

f:id:halya_11:20190331201351p:plain

またこれとは別に、「同フレーム内で同じTaskを処理せず次のフレームに回す」というルールがあります。
どういうことかというと、例えば次のようなBehavior Treeを考えます。

f:id:halya_11:20190331195824p:plain

100回ログ出力を繰り返すだけのTreeです。
これを実行すると同じフレーム内で同じLog Taskを実行しようとしたときに
次のフレームに処理が先送りされるため、Treeが完了するまでに100フレーム掛かることになります。

同フレームで処理するTaskの数を制御する

さて前節のように次のフレームに処理を先送りにしたくない場合、
Behavior ManagerのTask Execution Typeというフィールドを使います。

f:id:halya_11:20190331193731p:plain

これをNo Duplicates(初期値)に設定すると、前節の通りの挙動となります。
Task Execution TypeをCountにしてMax Execution Countを設定すると、
その数だけ次フレームの先送りが無効になり、同フレームで処理されるようになります。

f:id:halya_11:20190331200136p:plain

関連

light11.hatenadiary.com

light11.hatenadiary.com

参考サイト

opsive.com

opsive.com