「スイッチを押したら、ドアを開けたい」。やりたいことは単純ですが、スイッチはどうやってドアへ「開け」と伝えるのでしょうか。
こうした 別のBlueprintへ処理を頼んだり、出来事を知らせたりするやり取り を、ここでは通信と呼びます。ネット対戦の通信ではなく、まずは同じゲーム内にある部品同士の連携です。
代表的な方法は、Direct Reference・Blueprint Interface・Event Dispatcher の3つです。直通電話、共通の依頼書、受信登録した人への放送を思い浮かべると、それぞれの役割をつかめます。最後に「ボタンを操作すると橋が現れる」仕掛けへ、3つを組み合わせてみましょう。
この記事でわかること
- 相手へ処理を頼むことと、起きたことを知らせることの違い
- 3方式でも必要になる「参照」と「Target」の意味
- Interfaceの送り先、Dispatcherの受信登録の作り方
- 1つの仕掛けで3方式を使い、通知先を後から増やす実践
全体像:何を、誰へ伝えたいか
まず 参照(Reference) は、「今、処理したい相手の個体」を指す値です。レベルへ同じ設計図のドアを2枚置いても、右のドアと左のドアは別の参照になります。
ノードにある Target は、その処理を行う相手です。OpenDoorのTargetへ右のドアを渡せば、右のドアへ開くように頼みます。Targetをselfにすれば、自分自身が相手です。
| 方法 | 今回の言い方 | 例 |
|---|---|---|
| Direct Reference | 相手の具体的な処理を呼ぶ | この橋のExtendを呼ぶ |
| Interface | 共通の操作名で頼む | 選んだ相手へInteractを送る |
| Event Dispatcher | 起き たことを知らせる | 橋が開通したと通知する |
参照を使うのはDirect Referenceだけではありません。 Interfaceにも送り先が必要です。Dispatcherでは、通知を受け取る設定をするときに、発信元の参照を使います。

Direct Reference:相手の処理を直接呼ぶ
相手への参照から、そのClassの関数やCustom Eventを直接呼ぶ方法です。例えば、スイッチにBP_DoorのObject Reference型変数 TargetDoor を持たせ、その参照からOpenDoorを呼びます。
これは「このドアのOpenDoorを実行して」という直通電話です。どのノードを呼んでいるかが見えやすく、特定のスイッチとドアを対応付ける仕掛けに向いています(→ Level Blueprintと配置Actorの参照)。
一方、BP_DoorのOpenDoorを呼ぶ作りには、BP_Doorとして扱える相手が必要です。別の作りの宝箱へ、そのまま置き換えられるとは限りません。こうした 相手の作りにどのくらい頼っているか を、結合度と呼びます。頼る部分が多いと密結合、少ないと疎結合です。

直接呼び出すこと自体が悪いわけではありません。同じClassの別のドアへ参照を替えたり、複数のドアを順に呼んだりする使い方もできます。「ずっと1体だけの場合しか使えない」という制限ではありません。
Blueprint Interface:共通の操作名で頼む
Blueprint Interface は、相手が受け付ける操作名と、受け渡す値を共通にする仕組みです。例えば Interact という「操作する」依頼を用意し、ドアでは開く、宝箱では中身を出す、レバーでは倒す、と各Actorで反応を作ります。
送り手は、「この相手へInteractを頼む」と書けばよく、ドア用・宝箱用・レバー用の処理を順番に探す必要がありません。共通の書式の依頼書を、選んだ相手へ渡すイメージです。

図は、対応できる相手の例を並べています。1回のMessageで、この3つへ自動的に一斉送信されるわけではありません。MessageのTargetへ、今回操作する相手を1つ指定します。
使うときは、次の4つを揃えます。
- Blueprint Interfaceを作り、Interactなどの関数名を定義する。
- 受け手のClass Settingsへ、そのInterfaceを追加する。
- 受け手で、その操作に対する反応を書く。
- 送り手で
Interact(Message)を作り、Targetへ相手の参照を渡す。
Messageを送った相手がInterfaceを実装していなければ、その操作は何も起きずに終わります。「線はつながるのに反応しない」ときは、Targetに加えて、受け手のInterface追加と処理の実装も確認します。
Interfaceには値を返す関数も作れます。まずは入力・出力なしのInteractで往復しない依頼を試し、発展はBlueprint Interfaceの記事へ進めます。
Event Dispatcher:登録された相手へ知らせる
Event Dispatcher は、「橋が開通した」「HPが変わった」などの出来事を、それを受け取るように設定したイベントへ知らせる仕組みです。
通知を送る操作が Call、受け取るイベントを登録する操作が Bind です。放送に例えると、受信側は「どの発信元の、どの番組を聴くか」を先に決めます。

例えば橋にOnBridgeExtendedを 作り、表示担当と音担当が、その橋のDispatcherへそれぞれBindします。橋がCallすると両方が反応しますが、橋の開通処理の中へ「このUIを表示し、この音担当を呼ぶ」と書く必要はありません。
ここでの放送は、ゲーム中の全Actorへ無条件に届くものではありません。その個体のDispatcherへ登録したイベントだけ が呼ばれます。1つだけ登録して使うことも、複数登録することもできます。
また、Bindより前に送られた通知は、後から自動で再生されません。橋を動かす前に受信登録を済ませる、という順序も実践で確かめます(→ Event Dispatcherの接続と解除)。
使い分け:人数より、やり取りの役割を見る
「1体ならDirect、複数ならDispatcher」と人数だけで分けると、迷いやすくなります。まず、今回の連絡で何をしたいかを考えます。
| やりたいこと | 選ぶ目安 |
|---|---|
| 対応する橋のExtendを呼びたい | Direct Referenceで直接呼ぶ |
| 相手がボタンでも案内板でも、同じ操作キーを使いたい | InterfaceでInteractを共通にする |
| 橋が開通した後の反応を、表示や音の担当に任せたい | Dispatcherで出来事を知らせる |
疎結合にすると、後から別の受け手を足しやすくなります。そのぶん、登録先や実装先をたどる手間も増えます。小さな仕掛けは直接呼び出す形から始め、共通に扱いたい操作や、別の担当へ任せたい反応が見えてきたら分けて構いません。

実践:Eキーで橋を出し、開通を知らせる
Eキーを押すと、指定したボタンへInteractを送り、ボタンが対応する橋を出し、画面に「橋が開通した」と表示する仕掛けを作ります。
今回は3方式の接続を確かめるため、橋は板を表示する形 にします。踏む判定、伸びるアニメーション、専用HUDは、動いた後に追加できます。

① 橋とボタンの本体を作る
Third PersonのBlueprintプロジェクトを使います。Variantがある版はNoneにし、テンプレートの歩けるレベルを開きます。Actorを親にして BP_Bridge と BP_FloorButton を作ります。
それぞれへStatic Meshを追加し、エンジン標準のCubeを選びます。アセット選択欄でShow Engine Contentを有効にすると、EngineのBasicShapesから選べます。
| Actor | MeshのScale | Collision Presets |
|---|---|---|
| BP_Bridge | X=6、Y=2、Z=0.2 | BlockAll |
| BP_FloorButton | X=0.8、Y=0.8、Z=0.2 | BlockAll |
両方のSimulate Physicsをオフにし、Compile・保存します。レベルへ1個ずつ置き、ActorのRotationは0、Scaleは1にします。どちらも板の高さは20cmなので、Actorの中心を床の表面から10cm上にすると下面が床に接します。
最初は平らな床の上で、細長い板が現れるかを確かめます。Play開始位置から板とボタンが見え、プレイヤーが板の上に重ならないように置いてください。
② 橋を出す処理を作る
BP_BridgeのEvent Graphで、BeginPlayから次の2つを順につなぎます。どちらもTargetはselfです。
| 開始時のノード | 設定 |
|---|---|
| Set Actor Hidden In Game | New Hidden:true |
| Set Actor Enable Collision | New Actor Enable Collision:false |
これでPlay中の開始状態は、見えず、通り抜けられる板になります。非表示と当たり判定は別の設定 なので、両方を変えています。

My BlueprintのEvent Dispatchersへ OnBridgeExtended を追加します。Inputsはなしです。次にCustom Event Extend を作り、次の順で白い実行線をつなぎます。
DoOnce。Start Closedはオフ、Resetは未接続。Set Actor Hidden In Game。New Hiddenはfalse。Set Actor Enable Collision。New Actor Enable Collisionはtrue。Call OnBridgeExtended。Dispatcherをドラッグして「Call」を選ぶ。
2つのSetとCallのTargetはいずれもselfです。DoOnceは、最初の1回だけ先へ進めるノードです。橋側へ置くことで、別の入口からExtendを呼んでも、同じプレイ中に開通を繰り返し通知しません。

Compile・保存します。まだ外からExtendを呼んでいないので、Play時は板が消えたままで正常です。
③ ボタンへ「Interact」を受け付ける口を作る
Content Browserの「Blueprints → Blueprint Interface」から BPI_Interactable を作ります。最初の関数を Interact へ改名し、Inputs・Outputsはどちらも空のままCompile・保存します。Interfaceには操作名を定義し、ボタンを動かす処理は受け手へ書きます。
BP_FloorButtonを開き、Class Settings → Interfaces → Implemented InterfacesからBPI_Interactableを追加してCompileします。Event Graphで右クリックし、Interfaceの Event Interact を追加します。
ここへ同名のCustom Eventを自作するのではなく、追加したInterfaceのイベント を置きます。見つからない場合は、My BlueprintのInterfacesにあるInteractを右クリックして実装を開きます。今回は戻り値がないので、イベントとして実装できます。
④ ボタンから、対応する橋を直 接呼ぶ
BP_FloorButtonへ TargetBridge 変数を作ります。型は BP_BridgeのObject Reference、Instance Editableをオンにします。Class Referenceではなく、配置した橋の個体を指す型です。
Event Interactから、白い実行ピンのある Is Valid へつなぎます。Input ObjectにはGet TargetBridgeを入れます。Is Validは、その参照先が存在し、まだ使えるかを確かめます。
Get TargetBridgeの青い出力から Extend を呼ぶノードを作り、Is Validの成功側を、その白い実行入力へつなぎます。ExtendのTargetはTargetBridgeです。Is Not Valid側は何もせず終えます。

Compile・保存したら、レベルに置いたボタン を選び、DetailsのTarget Bridgeで、対応するBP_Bridgeを指定します。Instance Editableをオンにしただけでは相手は入りません。この割り当てまで済ませます。
これがDirect Referenceの部分です。ボタンは、指定した橋のExtendという具体的な処理を呼んでいます。
⑤ 開通の通知を、先に受信登録する
Outlinerで配置した橋を選び、Blueprints → Open Level Blueprintを開きます。右クリックから「Create a reference to[橋の名前]」を選び、配置済みの橋の参照を置きます。
その青い出力から Bind Event to OnBridgeExtended を作ります。Targetはこの橋です。Event BeginPlayをBindの白い実行入力へつなぎます。
Bindの赤いEventピンからドラッグし、「Add Custom Event for Dispatcher」で ShowBridgeOpened を作ります。そのCustom Eventの白い出力からPrint Stringをつなぎ、In Stringを「橋が開通した」、Durationを10秒にします。
Bindは登録の処理、ShowBridgeOpenedは通知が来たときの反応 です。Print StringをBeginPlayやBindの直後へ置くと、橋が開通する前に表示されてしまいます。

⑥ EキーからボタンへMessageを送る
Level BlueprintへActorのObject Reference型変数 CurrentTarget を作ります。これは「今、操作する相手」です。特定のボタンClass型にはしません。
レベルへ戻ってボタンを選び、同じ方法でLevel Blueprintへ配置ボタンの参照を置きます。先ほどのBindの白い出力へSet CurrentTargetをつなぎ、値へボタンの参照を渡します。開始時に、通知の登録と操作相手の設定を済ませる形です。
Compileしてから、グラフの右クリックでキーボードのEイベントを追加します。
- EのPressedから、白い実行ピンのあるIs Validへつなぐ。
- Input ObjectへGet CurrentTargetを入れる。
- Get CurrentTargetの青い出力から、封筒マーク付きの
Interact(Message)を作る。 - Is Validの成功側を、Messageの白い実行入力へつなぐ。TargetはCurrentTarget。
Is Not Valid側は何もしません。ここでは、Actor型の相手へ、BPI_Interactableで決めた操作名を送っています。Cast To BP_FloorButtonを挟む必要はありません。

⑦ 表示と通知を確かめ、受け手を増やす
両Actor・Interface・Level BlueprintをCompile・保存してPlayします。ゲーム画面をクリックしてからEキーを押します。
| 確認 | 期待する結果 |
|---|---|
| Eを押す前 | 橋の板は見えず、開通メッセージも出ない |
| Eを1回押す | 橋が現れ、その後「橋が開通した」と出る |
| Eを離して再び押す | 橋は出たまま。新しい開通メッセージは出ない |
| Stopして再びPlay | 橋が出ていない状態からやり直せる |
動かなければ、E直後のPrint Stringで入力を確かめます。次にCurrentTarget、ボタンのInterface、TargetBridgeの割り当てを確認します。橋は出るのに通知がないなら、Bindの白線・Target・赤いEvent接続と、橋のCallを調べます。
次にPlayを止め、Level Blueprintへ もう1個 Bind Event to OnBridgeExtended を追加します。同じ橋をTargetにし、最初のBindの後、Set CurrentTargetの前へ白い実行線で挟みます。
新しいBindの赤いEventピンから、別のCustom Event RecordBridgeOpened を作り、Print String「記録:橋 を開通」(Duration 10秒)へつなぎます。
再びPlayしてEを押すと、2種類のメッセージが出ます。橋のBlueprintを直さず、開通後の反応を増やせました。画面の上下順ではなく、両方の文が出たか で確認してください。今回は実績保存の代わりに、受信できたことをPrintで見ています。
⑧ 同じInteractを、別の種類へ送ってみる
Actorを親に BP_Sign を作り、BPI_Interactableを追加します。Event InteractからPrint String「案内板を読んだ」(Duration 10秒)をつなぎ、Compile・保存してレベルへ置きます。見た目が欲しければ、目印のCubeを追加できます。
Level Blueprintの Set CurrentTargetへ渡す参照だけ を、この配置したBP_Signへ替えます。EのMessageノードはそのままです。
PlayしてEを押すと、今度は案内板のメッセージが出て、橋は出ません。同じInteractという頼み方で、別のClassの反応を呼べました。確認後はCurrentTargetをボタンへ戻します。
おまけ:先に知っておくと良いこと
踏んで動くボタンや、伸びる橋にするには
今回のEキーは、通信を試すために、あらかじめ決めた相手へ送っています。目の前を狙って操作するなら、Line Traceで当たったActorをMessageのTargetへ渡します。
踏むボタンなら、Box CollisionのOverlapでプレイヤーを確認し、ボタン自身の同じ起動 処理へつなぎます。検出領域の設定はトリガーで扉を開ける実践を参考にできます。
橋を徐々に伸ばすなら、Timelineで位置を変え、FinishedからOnBridgeExtendedをCall します。「動き始めた」と「開通した」を分けておくと、表示や音も適切なタイミングで反応できます。
Castは、相手の型を確かめるために使う
Castは、参照先を指定したClassとして扱えるかを確認するノードです。新しい相手を探したり、別のActorへ作り替えたりするものではありません。
特定のCharacterだけが持つ機能を使いたいなら、Castして直接呼ぶ方法が役立ちます。一方、ボタンと案内板へ同じ操作を頼む今回は、Interfaceで操作名を共通にしました。選び方はInterfaceとCastingで詳しく扱います。
受信をやめたいときはUnbindする
UIの表示対象を別の橋へ替える場合などは、古い橋のDispatcherから、自分のイベントをUnbindして、新しい橋へBindします。相手が生きていても、古い通知を受けたくなくなる場面があるためです。
「破棄時に必ず解除しないとメモリリークになる」と一律に覚えるより、誰の通知を、いつまで受けたいか を決めます。他の受信者もまとめて外すUnbind Allは、個別の解除と区別してください。
共通の状態にも、読む処理と通知は必要
ゲーム全体のスコアをGameStateなどへ集めても、UIが値を読んだり、変化を受け取ったりする連携は残ります。「置き場所を決め ること」と「そこへどう連絡するか」は別です。
自作Componentも同じで、体力を減らす入口は関数、変わったことの通知はDispatcher、と分担できます。
まとめ
今回の入力側は、選んだ相手へInteractを送りました。ボタンは対応する橋のExtendを直接呼び、橋は開通したことを登録先へ知らせました。3方式は、同じ仕掛けの中で違う役割を受け持っています。
自分のグラフでも、「相手に何かしてほしいのか」「起きたことを知らせたいのか」を分けて見ると、処理の置き場所と、必要な参照が見えてきます。通知の登録を詳しく試すならEvent Dispatcher、共通の操作を増やすならBlueprint Interfaceへ進めます。