はじめに
この記事はK3 Advent Calendar 2025の5日目です。
UE初心者の壁のひとつであるところのInterfaceとEventDispatcherについて、その存在の嬉しさがわかる実装例を元に解説していきたいと思います!
注意として、InterfaceとEventDispatcher自体がある程度どんなものかは知っている前提で解説していきます。「機能としては知ってるけど、どういうときに使ったらいいんだろう?」となっている人が本記事のターゲットになります。
実装には、UE5.6のThirdPersonTempleteを使用します。
Interfaceの嬉しさ
ギミックを動かすスイッチの作成を例に解説していきたいと思います!
アクションゲームにありがちなアレです。スイッチを押すと、ドアを開けたり、リフトを動かしたり、いろいろできる感じのものを想定します。
Interfaceを使わない場合の実装
まず、以下のクラスを作ります。他BPとの通信部分は後で。
では、まずはスイッチを踏むとドアが動く処理を作っていきます。
BP_SwitchにActorの参照型変数TargetActorを作って、InstancedEditableにします。(画像の瞼を開く)

そして、BeginOverlapイベントでTargetActorをBP_Doorにキャストし、Openイベントを呼び出します。

そしたら、BP_SwitchとBP_Doorをレベルに置いて、置いたBP_SwitchのTargetActor変数にBP_Doorを指定します。(画像の赤線部分)

プレイしてスイッチを踏むとドアが開きますね。
では、次に同じBP_Switchクラスを使ってリフトを動かせるようにしましょう。
BP_DoorへのキャストのノードのCastFailedから伸ばして、今度はBP_Liftにキャストし、StartMoveイベントを呼び出します。

そうしたら、BP_Liftと新しいBP_Switchをレベルに置いて、新しいBP_SwitchのTargetActor変数をBP_Liftに変更します。

プレイして新しいスイッチを踏むと今度はリフトが動きます。
はい、ここまでで勘の良い方はお気づきかと思いますが、このやり方をするとスイッチで動かしたいものが増えるたびにBP_Switchの分岐がどんどん増えていきます。地獄ですね。

じゃあ、ドア専用スイッチ、リフト専用スイッチ…というようにスイッチのクラスを分ければいいと思う人もいるかもしれませんが、その方法でも動かしたいものが増えるたびにクラスが増えていってどのみち地獄です。

こんな地獄を解消してくれるのがInterfaceです!
Interfaceを使う場合の実装
用意するクラスは先ほどと同じです。
新しく、BPI_Gimmickという名前でブル―プリントインターフェースを作成します。
そして、Activateという名前の関数を定義します。

そうしたら、BP_DoorとBP_LiftにBPI_GimmickをImplementし、ActivateにそれぞれOpenとStartMoveを繋げます。

BP_Switchの方は、OverlapイベントでTargetActorからActivateを呼び出します。
さっきと比べて、随分コードがスッキリしたのがわかると思います。

これで実行してみると、なんと先ほどと同じ挙動になっています!
これで動かしたいギミックがどれだけ増えても、BP_Switchの実装を変更する必要がなくなりました!地獄のスパゲッティBPを書いたり、クラスが死ぬほど増えたりしません!嬉しいですね!
また、TargetGimmickを配列にしてあげれば、1つのスイッチで複数のギミックを動かすことも可能になります。

一つのスイッチのTargetGimmick変数に、BP_DoorとBP_Liftを両方設定

EventDispatcherの嬉しさ
プレイヤーキャラクターが近くにいるとき、プレイヤーのジャンプに反応して自分もジャンプする敵エネミーの作成を例に解説していきたいと思います!
マリオとかでよく見るアレですね。
EventDispatcherを使わない場合の実装
まず、Characterを継承したBP_Enemyを作ります。
スケルタルメッシュに適当にMannyを設定するなどしましょう。
そして、5m×5m×2m四方のBoxCollisonも追加します。これがプレイヤーを探知する範囲になります。

では、次にプレイヤーが範囲内に居るかどうか判定する処理を書いていきます。
プレイヤーが範囲内にいるかどうかを判定するbool型変数PlayerOverlapedを作り、BoxCollisionのBeginOverlapとEndOverlapに↓のような処理を追加します。

では、次にプレイヤーがジャンプした瞬間を判定して、自身をジャンプさせる処理です。
プレイヤーがジャンプした瞬間の判定には、Characterがデフォルトで持っている、現在のジャンプが何段目をカウントするJumpCurrentCountを用います。
Tickで毎フレームJumpCurrentCountを監視し、0から1以上になったタイミングで、PlayerOverlapedがtrueならジャンプをさせます。BPは↓のような感じになります。

これでBP_Enemyをレベルに置いて、近くでジャンプをしてみましょう。するとEnemyもジャンプするかと思います。
ただ、この実装、だいぶ気持ち悪いな…と思ったかと思います。特に、ジャンプをしたかどうかの判定のために、Tickで毎フレームJumpCurrentCountを監視するという所が非直感的かつ周りくどい手段を取っていて今後バグを生みそうですし、Tickを使ってるので処理も重たいです。
プレイヤーキャラクターの方の実装をいじって、「現在ジャンプ中」かを判定するフラグを作っても良いですが、どのみちTickを使って監視をするという点は変わりません。
もっとシンプルに、「プレイヤーがジャンプしたタイミング」でイベントを実行できたら良さそうだと思いませんか?それを実現してくれるのがEventDispatcherです。
EventDispatcherを使う場合の実装
まず、プレイヤーのBPである、BP_ThirdPersonCharacterで、EventDispatcherを追加し、名前をED_OnJumpedとします。そして、Jumpノードの後ろにCall ED_OnJumpedノードを追加します。

そして、BP_Enemyに戻ります。
まず、Tickにごちゃごちゃ書いたBPを全て消去し、BeginOverlapとEndOverlapを↓のように変更します。

プレイヤーが探知範囲内に入ったときに、ED_OnJumpedに、JumpイベントをBindし、探知範囲から抜けたときはUnbindするという操作を行っています。
つまり、Bind中に、BP_ThirdPersonCharacterでBP_ED_OnJumpedがcallされると、それに連動してBP_EnemyもJumpをするということですね。
実際に、この状態でプレイしてみると、先ほどと同じ挙動になっていることがわかります。
このように、EventDispatcherを使えば、「○○が○○した時」のタイミングを別のBPクラスでも簡単に、直感的にとることができます。Tickも使用しないので処理負荷的にも非常に嬉しいのがわかると思います。
まとめ
このように、InterfaceとEventDispatcherはちゃんと使えると処理負荷、可読性、保守性、拡張性などなどが非常に良くなる嬉しい性質を持ってます。適切に使って快適な開発ライフを送りましょう!
おまけとして、InterfaceとEventDispatcherを使うと幸せになれる場面を他にも何例か紹介しようと思います。どう使えば嬉しくなれるかを考えてみてください!
Interface
- 種類が多く、固有の効果があるアイテムの実装
- プレイヤーの目の前にある物体へのインタラクション
- 固有効果を持っている武器、防具の実装
EventDispatcher
- ゲームの進行度合いに応じてステージから消えたり出現したりするアイテム
- ゲーム中一度だけしか発生しないイベント
- 所持アイテムやステータスが変更された時のUIの更新



