Unity x BehaviourTreeで遊んでみる

こんにちは。みなさまお元気しておりますでしょうか?
今日は私のチームで利用している内製のBehaviourTreeについて紹介したいと思います。

実際のコードなどについては共有できませんが、少しでもAIの知見が役に立てばということで書いておきたいと思います。
あと、詳しいBehaviourTreeの説明はしないので他のページをググって読んでください。
(Standardな実装って知らないので、もしかしたらBehaviourTreeの別の解釈をしているかもしれませんのであしからず!)

予測出来うるゲーム開発における振る舞い定義の課題

  • 企画とエンジニアがツーカーの仲でないと企画の意図したAIを実現するのに時間がかかる場合がある
  • APIを提供し、スクリプトでAI書いてもらう場合は品質の担保が難しいこともある
  • 直接振る舞いを書いている場合、企画が大きく変わった時にAIの組み換えが困難な事がある

振る舞いを実装する場合上記のような課題があるかと思います。そこで私のチームではBehaviourTreeを内製して利用しています。

AI系のライブラリはAssetStoreにも売りだされているものが有りますが、利用する側の事情としては下記のような課題があり、内製したほうが結果コスト低いしノウハウ貯まるよね、ということで作りました。

  • エディタライセンスを採用している物が多く、エンジニアやAIプランナーの増減に応じて適切なライセンス管理をするのは大変
  • ゲームのコアとなる部分なので少なくともリリース後までずっと付き合い続ける必要がある
  • dll提供のライブラリもあるので、問題発生時の対応を検討すると内製してメンテしたほうが品質をコントロールしやすい

BehaviourTreeの魅力

  • グラフィカルなエディタによる自由な組み換え
  • 視覚化されたツリーにより振る舞いの課題を明確化できる
  • Tree構造によりいくらでも作れる
  • 各種アクションの開発のスケーリングが容易
    • Action自体で完結しているので設計フェーズできちんと定義できていれば複数人で実装できるので楽
  • 程よい実行コスト
    • DecoratorやActionの使いドコロを間違えなければそれほど気にならない

とまぁ、エンジニアにとっては非常に魅力的です。考えて組んだものがそのまま動いてくれるので良いですね。

AIプランナーと喋っている時も、実際の課題がツリーとして表現できるのでこの遷移が悪い、などと指摘し合えるのが非常に助かっています。
(逆にBehaviourTreeへの習熟度が低い状態だとなんでこれで動いているんだろう?というふうになってしまうのでエディタ側でわかりやすいサポートが必須となりますが、、、)

StateMachineやノードベースのグラフィカルエディタもありますが、設定項目の数やルールを考えるとできることが少ないBehaviourTreeのほうが(僕の)好みに合っていました。

BehaviourTreeの欠点

  • (当たり前ですが)事前に適切なActionを定義していないとそもそも使いものにならない
  • 適切な学習を行わないとそもそもプランナー/エンジニアがいじれない。StateMachine比べると学ぶべきことが多い
  • StateMachineに比べれば初期化や実行でコストがかかりやすい。
  • 巨大化したツリーはとても見づらい上に実行コストがかかりやすい
  • エディタがないと辛かった

使ってみよう。BehaviourTree

e277343c3961d35116f624c2633fc7c6709efe

弊社ではこんなかんじのエディタをUnityで作って利用しています。Windows向けに.Netで書いても良かったのですがMacの事を考えるとUnityで統一しておいたほうが運用が楽です。
それでは早速ですがAIを動かしてみましょう。AIと言うと非常に広義になりますので、ここでは時間経過において振る舞いを変えるもの、ということにしておきます。

Unityちゃんを動かす

SD Unityちゃんを使ってSaluteを再生したあと2秒待つつ→以降繰り返し、という振る舞いを定義してみましょう。

事前にAnimationを再生するBehaviourTreeのActionと、指定時間何もしないというActionを事前にスクリプトで定義しエディタ上で割り当てます。
初めて利用する場合はこういったAIのふるまいを自分たちで作らなければいけませんが二度目は使い回しがたいていできるのでさくっと書いてしまいましょう。

5eeb7df1f4bcc7f1d1efd7817fb577ea5c6e1e

b95961347faf992b1a6b5ab06269ac8f6997d3

今回は選択の条件となるDecoratorは利用しません。

BehaviourTreeではSelector/Sequencerの評価が終了すると初期状態になるので、手続き型のループを書きたい場合はSequencerを使い、実行したいActionを並ばせれば結果的にループとなります。
Sequencerは成功し続ける/最後のノードに行くまで評価を行いますので上記の例ではAnimation再生とWaitが終わったらまた最初から評価を行う、という流れになります。

複雑なツリーだとこのように単純にループを書けないことも有りますが、大抵はなんとかなるはずです。

Componentの割り当て

082a7e1a2bdf67adc2a9f1fc03073c68a56624

BehaviourTreeのRuntimeは弊社の場合Componentとして実装しているのでComponentをくっつけてあげます。

再生してみる

Unityのプレイボタンを押すところからビデオにとってみました。

はい、(僕が)思った通り表示されていそうですね。

Animation実行終了後、2秒待ってから再度Animationを再生出来ています。

Tips

これだけだと特に学び無いのでEditor Tipsでも。

  • こういうGUI作る上で一番重要なのは一発目にGUI.EndGroup();をかます事だったりします。DefaultのClippingっぽいのなくなるのであとは自由に書けるはずです。
  • Editorの場合Awake中のリソースの読み込みは禁止されているのでちゃんとしたタイミングで読み込みましょう
  • Reloadに耐えられるようにUnityのSerialization/Deserializationをきちんと学びましょう

まとめ

BehaviourTreeを使うとこんな感じで2回目以降はこみいったスクリプトを書かなくてもグラフィカルエディタを使って振る舞いを組むことができます。
これぐらいの超小規模な振る舞いだとあまりメリットを感じませんが、複雑な振る舞いを作る場合は部分部分で流用も可能ですし、色々と組み換えが楽なので良いです。

1度アクションを作るとあとあと使い回ししやすい資産としても残りますのでいちAIライブラリとしてとても汎用性が高いのではないのでしょうか?

(といってもGame SpecificなActionってめっちゃゲームに依存するので流用が簡単ではないのですが、、、)

それではみなさんも楽しいUnityライフを

License表記

ユニティちゃんライセンス

このコンテンツは、『ユニティちゃんライセンス』で提供されています