読者です 読者をやめる 読者になる 読者になる

妹でもわかるUnrealEngine4

毎日更新? 妹に説明するために書いてるけど、たまにわかってない場合もあるUnrealEngine4を中心としたゲーム制作の話。略すとイモリアル

毎日更新? 妹に説明するために書いてるけど、たまにわかってない場合もあるUnrealEngine4を中心としたゲーム制作の話。略すとイモリアル

ビヘイビアツリー研究① サービスとデコレーターとタスクの違い

ビヘイビアツリー ブループリント UE4.11

4/11 FinishExecuteについて少し追記

妹「そろそろ花粉が収まってきたので、ぷちコンのゲームを作り始めようと思うんだけど」

「今から?」

妹「間に合うかどうかはあれだけど。とりあえずAIで思いついたのを作ってみたいんだけど、ビヘイビアツリーの、サービスとデコレーターとタスクっていうのは、これは一体なんなんじゃろうかと」

「それはだいぶ間に合わなそう、というか1回では済まなさそう」

f:id:una_unagi:20160410225247p:plain

「とりあえず前回のぷちコンで作ったビヘイビアツリーで、まあだいぶ忘れちゃってる感じなんだけど、とりあえず[ルート]の詳細設定で、どのブラックボードを使うのか設定して、あと敵が近くに居るか調べるサービス[BT目視確認]と、実際に弾を発射する[BT弾発射]というのを作っている。」


タスク

何かをする。最終的にこれがどこかに無いと、何もやらないビヘイビアツリーになる。
中身としては普通のブループリント。

標準のタスクにも、目的に向かって進むMoveToとか、一定時間待つWaitとか、あと音を鳴らしたりとかもあるけど、基本的に何か自作することになる可能性大。
弾を発射するというのは標準タスクでは出来ないので[BT弾発射]を作る必要があった。

サービス

これも何かをするんだけど、タスクとの違いは、自分の番が来たら実行するというタイミングではなく、定期的に何度も実行すること。
ティック的な存在なので、実行する間隔を設定して、前回実行時からの経過時間も取得できる。

そのノードから出ている矢印の、先にあるノードが実行されてる時で、かつ予定の時間が来ると実行される。
今回の例でいうとBT目視確認はルートの下で、そこから全部の矢印が出てる、一番根元のとこなので、常に実行対象になる。

[BT目視確認]は敵が、つまりプレイヤーが、近くに居るかどうかを調べて、居たらブラックボードの攻撃可能フラグをtrueにする機能を持っている。
そのフラグは後で別のデコレーターが使う。

デコレーター

そのタスクやサービスを実行するかどうか決める。
この条件に合ってれば実行とか。

基本は1度実行したら終わりなので、何度も繰り返し実行する場合はLoopをInfinite Loopにチェックを入れて使う。
条件の複合も出来るので、あれとこれの条件に合致した場合実行みたいこともやれる。

MoveToのとこにあるTimeLimitは、2秒間歩いて敵に接触出来なかったら、いったん打ち切って最初のループに戻すため。
そうしないと追いつくまで永遠に歩き続けて、その間他のノードに移行もしないので、弾発射をするタイミングがなかったから。


妹「うーん……わかるような、わからないような感じなんだけど、例えば敵が近くにいるのかいないのか、弾を発射するのかしないのかっていうのは、タスクの中でやってもいいんじゃないの? そしたらサービスは作らなくて良かったのでは?」

「それだと弾を発射しない場合でも、タスクを実行したことになっちゃったんだよ。Selecterノードには、つながってるノードのどれか1つを実行するという特徴があるんだけど、実行しちゃうと、結果はどうあれ実行出来たからヨシ、と判断されてしまって、予定してたのと違う動作になってしまった。その後タスクのFinishExecuteでFalseを設定する方法も見つけたけど、実行判定にはデコレーターを使うのが良い使い方らしい」

妹「あれもこれも全部タスクに書いちゃうというのでは駄目なの?」

「そこまでやるとビヘイビアツリーの効能がなくなるんだよ。個々の要素をシンプルにして組み合わせていくと、後からノードを組み換えて調整したり、タスクを別のキャラに流用したり、プログラマー以外の人が調整しやすくなったり、というメリットがあるけど、1つのタスクにまとめてしまうと意味がない。というか敵キャラのブループリントに直接書いた方が早い。それでもAIとしては機能するし、動き方もかわらないから」