この記事について
筆者が初めてStateTreeを見た時なぜこの機能が必要(便利)なのかがわからなかったのですが、試しに作ってみるうちになんとなくわかってきたので、ある場合とない場合の違いについてまとめてみました。
わかったこと
まずStateTreeはゲーム開発において必須の機能ではなかったです。(UEを作っている会社(Epic)の人がスライドで推薦していたのでほぼ必須かと思っていたのですが、いざ使ってみたら全然そんなことはありませんでした)
基本的に何かのActorの制御をしたいときは、(語弊を恐れずに言えば)1つにつき1つのBPだけ用意すれば十分動くものを作ることができます。
ではなぜStateTreeのような子BPも使うかというと、親BPを見やすい形に整理できるからでした。
(さらにweb開発経験者向けにいうと、webでいうコンポーネント指向での実装ができるからです。)
具体的な例
それでは具体的に公式リファレンスに沿って説明してみます。
チュートリアルでは5回攻撃が当たったら壊れる壁をStateTreeを用いて作成するのですが、壊れるかどうかの判定を壁ActorのBPからStateTreeに逃す実装をしていて、実際に実装したものが下記になります。
StateTreeを使うと壊れる場合をイベントとして切り出すことができるため、BPの中がイベントごとで状態がまとまり後からのソースコードリーディングがとても楽になっています。
一方で、親BPだけの場合は攻撃を受けるイベントで壊れるかどうかまでをひと繋ぎにする必要があり、後からのソースコードリーディングに辛みがあります。(下記図にて見比べてみてください)
※StateTreeを使った場合(HitとDestroyがどこで行われているか一目瞭然)
※StateTreeを使わない場合(HitとDestroyがどこで処理されているかわかりにくい)
StateTreeの全体感
また影響範囲全体の視点だと、BPとStateTreeは以下のような親子関係となっていました。
※正直StateTreeがある方が複雑な構成になるのでとっかかりにくいのですが、vueの経験からコンポーネントの使い回しは工数削減に非常に役立つのがわかっているので、個人的には良くできた仕組みだなと思います。
↑StateTreeTaskの親BPの取得でcast to 個別の親BP
を使う必要があるため、使い回しはできなさそうで、あくまで整理ができるのが強みの機能のようです。
まとめ(結論)
- StateTreeを使うとActorに直接つけているBPが、通常はひとまとめの闇鍋状態のところをイベント単位に整理できるため運用保守が楽になります。
- 一度準備したイベント(StateTreeTask)を使い回すことができるので、概ね同じ処理をするけどActorごとにBPが異なるような場合(雑魚キャラの作成の時など)に力を発揮します。
↑これはできなさそうでしたm(__)m
StateTreeの機能について思ったこと(余談)
今回の気づきを通して、(通常は親BPをコメントで整理すれば良いので、)大前提としてStateTreeは初手では作らなくても大丈夫なのかなと思いました。
ただ機能を拡張するに伴ってBP内の各種処理の影響範囲がどんど大きくなってコメントエリアからはみ出してしまって機能のまとまりがわかりにくくなってしまったりする場合がいずれ来ます。
そんな時に、別ファイル(StateTreeTask)に切り出しつつその総称と関係性をStateTreeで管理することで親BPを整理された状態に保てるようになるので、プロダクトが大きくなってきてからの有用性は高いと思いました。
しかしコンポーネント指向を知らない完全初心者の方が使うとドツボにハマりそうだなとも思ったので、そういう方はBPファイルが大きくなって管理が辛くなってきてから整理のために使うようにしてみると、良さがわかったり使いこなせたりするのでおすすめだと思いました。