ゲーム作りが大好きな人のブログ

ゲームを作るのが大好きな人のブログ。UE4とBlender、MAYA(LT)、3DCoatを使用しています!

【UE4】イベントディスパッチャーをCEコマンドで代用してみた話

※ 本記事はUE4.25.4で調査しています
Unreal Engine 4 (UE4) Advent Calendar 2020 その3」5日目の記事でございます。
qiita.com


先日ヒストリア様主催のゲームジャムがあり参加させていただきました。以前から

  • 何も手を付けてないUE4を手渡され「数日以内にゲームを作れ」というお題が来た時に、素早く分かりやすいゲームフローを組むにはどうすれば良いか

みたいな事をよく妄想(?)していたのでゲームジャム時とその後に色々と検証してみました。今回はその結果報告です。具体的には「イベントディスパッチャーをCEコマンドで代用してみた」というお話でBlueprintメインのお話になります。

はじめに

最終的に完成したものはシンプルではあるものの人によって賛否が出そうと思っています。なので、この記事に書かれている内容は推奨するものではなく、あくまで一つの案程度に捉えていただけると幸いです。

ゲームフローを制御するにあたって

ゲームフローを制御する際にイベントディスパッチャーを使用する事が多いと思います。例えば

  • UIアニメーション終了時にイベントディスパッチャーの呼び出し
    • 例1)フェードアニメーションが終了した時
    • 例2)ゲーム開始・終了時に出すUIのアニメーションが終了した時


こういった時にイベントディスパッチャーを使うと非常に効率よくフローが組めます。Tickで監視せずにイベントドリブンな形で実装できるので非常に優秀です。ただ常々思っていた事がありまして……

イベントディスパッチャーは気を使う事が多い

自分が思ったのは下記の2点。

1. ノード整理が多くなりがち

連動させるカスタムイベントには赤色の線が表示されますが、これがノード整理に気を使いやすいと考えています。この辺りはBPを整理するプラグインを使えば綺麗になるかもしれないです(申し訳ない、この点に関してはプラグインを持ってないので未検証です)。

f:id:toofu0:20201203215826p:plain
▲ 運命の赤い色で結ばれますが、この糸で整理がしにくい時が……

2. バインドとアンバインドを考慮しないといけない

状況に応じてイベントディスパッチャーに登録されているカスタムイベントを変更しなければいけない時があります。その際は「以前のイベントのアンバインド」と「次に使用するイベントのバインド」が必要になる時があります。これらは単純に作業の手数を増やす形になりますし、物によってはバグの原因になるといった弱点があります。

f:id:toofu0:20201204015742p:plain
▲ わちゃわちゃしてきた例。出来れば関数を呼ぶだけで終わるくらいのシンプルさが欲しかったり。ちなみにUserWidgetクラスにはBindToAnimationFinishedというDelegate用オブジェクトがデフォルトで付いていますが、今回は分かりやすく説明するために使っておりません。
 

「CEコマンド」を使ってみる

そこで今回はイベントの遷移にExecuteConsoleCommandからCEコマンドを使って直接カスタムイベントを叩く形を検証しました。これらの詳細に関してはキンアジさんのブログで素晴らしく丁寧に解説されておりますのでソチラを見るのが良いかと思います。
kinnaji.com

ちなみにShipping(製品出荷モード)でも使えます。それでは実際の流れを画像で説明します。

レベルブループリント

f:id:toofu0:20201203210441p:plain

  • BeginPlay
    • フェードウィジェットを作成→フェードイン関数を呼びます。第一引数にはアニメーション終了時に実行するカスタムイベントの名前を記述する事でフェードイン終了後に「FinishFadeIn」カスタムイベントが呼ばれるように設計しています。
  • FinishFadeInカスタムイベント
    • こちらでは1秒待機した後にフェードアウト関数を呼ぶようにしています。第一引数にはFinishFadeOutを呼ぶようにしています。

フェードウィジェット

フェードアニメーションの作成手順は割愛しますが、やっている事は画面全体を覆う黒い板のアルファ値を0~1(もしくはその逆)にしているだけです。
f:id:toofu0:20201203210631p:plain

  • FadeIn関数
    • 第一引数はStringにし関数実行直後にその値を保存します。その後フェードインアニメーションを再生します。
  • FadeOut関数
    • FadeIn関数と中身はほぼ一緒で呼ぶアニメーションがフェードアウトになっただけの物になります。

f:id:toofu0:20201203210837p:plain

  • [イベントグラフ] OnAnimationFinished

FadeIn、FadeOut関数で保存した文字列が空でなければExecuteConsoleCommandを実行します。

実際の動作【動画】

youtu.be
問題なく出来てますね、よかったよかった。

CEコマンドによるゲームフローのメリット・デメリット

  • メリット
    • 実装が非常に早くて楽。他のオブジェクトにも簡単に適用できる。
      • 製作時間が少ないプロジェクトでは有用
    • ノード構成が分かりやすい(関数を呼ぶだけで終わるシンプルさ)
  • デメリット
    • カスタムイベントの名前を変えた時に不具合が起きやすい。その名前を使用しているオブジェクト達のコマンドを変えないといけない。
      • 実行されなくなるだけなので不具合としては特定しやすいのがまだ救いとも言える。ただし気付かぬ内になってるパターンもあるのでその場合は見つけるまでが大変。
    • CEコマンドはそのレベルに存在する全てのサブレベルの同名カスタムイベントを実行するので名前被りすると不具合に発展する。
      • 逆にそれを利用してフローを組み立てる事も出来るので物は使いようとも言える。
    • 呼べるイベントはレベルブループリントのカスタムイベントのみ。

 

CEコマンドでゲームフローを実装してみた感想

個人的には即席の割には使いやすくて良かった。デメリット欄でも書きましたが気付かぬバグが発生する可能性は十分にありますので、ゲームジャムやプロトタイプ以外の時間のあるプロジェクトの場合はやり方を色々と考えた方が良いですね。

おまけ1

katze.hatenablog.jp
イベントディスパッチャーですが、こちら様のサイトにあるC++での変数化をしてしまえば一つのオブジェクトに絞る事が出来るので毎回Unbindする必要性がなくなりそうです(動かす所までは確認。ただ私個人としては長期運用実績がないです)。

おまけ2

ゲームジャムで作ったゲームはこちら。何も手をつけてないUE4から始めて16時間で完成しました。ゲームエンジンってしゅごい。
www.youtube.com