Blueprintでアクター 間通信を行う方法は主に3つあります:「Direct Reference(直接参照)」「Blueprint Interface(インターフェース)」「Event Dispatcher(イベントディスパッチャー)」です。
この記事では、これら3つの通信方法の特性と使い分けを解説します。
Direct Reference(直接参照)
概要と使い方
Direct Reference は、最もシンプルで直感的な通信方法です。特定のBlueprintクラスの変数や関数を直接呼び出す方法で、「このアクターの、この関数を実行する」という明確な指示を出します。
使用例:
- プレイヤーキャラクターが、目の前にある特定の「ドア」アクターの
OpenDoor関数を呼び出す。 - 親クラスが、子クラスの特定のコンポーネントのプロパティを直接変更する。
Blueprintの例(プレイヤーからドアへの参照):
- ドアアクター(
BP_Door)の参照をプレイヤーアクター(BP_Player)の変数に格納します(例:BeginPlay時やOverlapイベント時)。 - その変数からピンを引っ張り出し、呼び出したい関数(例:
OpenDoor)を直接検索して実行します。
// BP_Playerのイベントグラフ
// 参照変数: TargetDoor (型: BP_Door)
If TargetDoor Is Valid:
Call TargetDoor.OpenDoor()
メリット・デメリット
| メリット | デメリット |
|---|---|
| 実装が簡単 で、学習コストが低い。 | 依存性が高い (Tight Coupling)。 |
| パフォーマンスが良い。 | 参照先のアクターが変更されると、参照元も修正が必要になる。 |
| 処理の流れが追いやすい。 | 汎用性が低く、再利用が難しい。 |
ベストプラクティス
- 特定の単一のアクター との通信や、親子関係など構造が固定されている 場合に限定して使用しましょう。
- 参照を取得する際は、必ず
IsValidノードで参照が有効かチェックする習慣をつけましょう。
Blueprint Interface(インターフェース)
概要と使い方
Blueprint Interface は、C++のインターフェースに相当する機能で、「このメッセージを受け取ったら、どう処理するかは受け取り側が決める 」という、契約のようなものです。
インターフェース自体は処理を持ちません。インターフェースで定義された関数(メッセージ)を実装したアクターであれば、どのクラスであっても そのメッセージを受け取ることができます。これにより、通信元は通信相手の具体的なクラスを知る必要がなくなります(疎結合 )。
使用例:
- プレイヤーが「インタラクト」ボタンを押したとき、目の前にある「ドア」「スイッチ」「宝箱」など、インタラクト可能な全てのアクター に
Interactメッセージを送る。
Blueprintの例(Interfaceの作成と使用):
- Interfaceの作成:
BPI_Interactableというインターフェースを作成し、Interactという関数を定義します。 - 実装: ドア(
BP_Door)や宝箱(BP_Chest)のクラス設定でBPI_Interactableを実装します。 - 処理の記述: 各アクターのイベントグラフに
Event Interactノードが出現するので、それぞれの処理(ドアを開ける、宝箱を開ける)を記述します。 - 呼び出し: プレイヤー側は、目の前のアクターに対して
Message Interactノードを呼び出すだけです。
// BP_Playerのイベントグラフ
// TargetActor: 目の前のアクター (型: Actor)
Call TargetActor.Interact (Message)
メリット・デメリット
| メリット | デメリット |
|---|---|
| 疎結合 (Loose Coupling)を実現し、拡張性・保守性が高い。 | Direct Referenceに比べて実装手順が多い。 |
| 複数の異なるクラスに対して共通のメッセージ を送れる。 | 処理がインターフェースと実装クラスに分散するため、追跡が少し複雑 になる。 |
| 汎用性が高く、再利用しやすい。 |
ベストプラクティス
- 「〜できるもの」 という共通の機能を持たせたい場合に積極的に使用しましょう(例:
BPI_Damageable,BPI_Usable)。 - プロジェクトの初期段階から、汎用的な通信にはInterfaceを使 うことを検討しましょう。
💡 補足:Interfaceでも戻り値は使える
Blueprint Interfaceの関数は、戻り値(Output)を定義できます。例えば、
BPI_InteractableのGetInteractionText関数で、インタラクト時に表示するテキストを返すような設計が可能です。戻り値がある場合、呼び出し側でMessageノードではなく通常の関数呼び出しノードを使用します。
Event Dispatcher(イベントディスパッチャー)
概要と使い方
Event Dispatcher は、特定のイベントが発生したことを、そのイベントに興味を持っている全てのアクター に通知するための仕組みです。これは「一対多 」の通信(1つの発生源から複数のリスナーへ)であり、プログラミングにおける「オブザーバーパターン 」(またはPublish-Subscribeパターン)とも呼ばれます。
通信元はイベントを「発火」させるだけで、誰がそのイベントを受け取るかを知る必要はありません。通信相手は、事前にイベントに「バインド(登録)」しておく必要があります。
使用例:
- UIの「ゲーム開始」ボタンが押されたとき、プレイヤー、ゲームモード、BGM管理アクターなど、複数のアクター に通知する。
- 敵が倒されたとき、スコアUI、ドロップアイテム生成システム、実績システムなど、複数のシステム に通知する。
Blueprintの例(Event Dispatcherの作成と使用):
- Dispatcherの作成: イベント発生源のアクター(例:
BP_GameMode)にOnGameOverというEvent Dispatcherを作成します。 - 発火: ゲームオーバーになったタイミングで
Call OnGameOverノードを実行します。 - バインド: 通知を受け取りたいアクター(例:
BP_ScoreUI)のBeginPlayなどで、Bind Event to OnGameOverノードを使って、カスタムイベントを登録します。
// BP_ScoreUIのイベントグラフ (バインド)
Bind Event to OnGameOver (Event: Custom Event ScoreUpdate)
// BP_GameModeのイベントグラフ (発火)
Call OnGameOver
メリット・デメリット
| メリット | デメリット |
|---|---|
| 多対一の通知 が非常に容易。 | バインドとアンバインドの管理が必要。 |
| 通信元と通信相手が完全に独立している(最も疎結合 )。 | 処理の流れが追いにくくなることがある。 |
| UI操作やゲーム状態の変化など、グローバルなイベント に適している。 |
ベストプラクティス
- イベントを受け取ったアクターが不要になったら、必ず
Unbind Eventノードで登録を解除(アンバインド)し、メモリリークを防ぎましょう。 - ゲーム全体に影響するイベント (ゲーム開始/終了、ポーズ、スコア更新など)に使うと効果的 です。
3つの通信方法の使い分け
どの通信方法を選ぶべきか迷ったときは、以下のフローチャートと比較表を参考にしてください。
通信方法の選択フローチャート
- 通信相手は特定の単一アクターか?
- Yes →Direct Reference を検討。ただし、将来的に通信相手が増える可能性があるならInterfaceへ。
- No → 次へ。
- 通信相手は「同じ機能を持つ複数の異なるクラス」か?
- Yes →Blueprint Interface。疎結合で拡張性を確保。
- No → 次へ。
- イベントを「不特定多数」に通知したいか?
- Yes →Event Dispatcher。UIやゲーム状態の通知に最適。
比較表
| 通信方法 | 結合度 | 汎用性 | 主な用途 |
|---|---|---|---|
| Direct Reference | 高い(密結合) | 低い | 特定の単一アクター、親子間通信 |
| Interface | 低い(疎結合) | 高い | 共通機能を持つ複数の異なるアクター |
| Event Dispatcher | 最も低い(疎結合) | 高い | UIイベント、ゲーム状態のグローバル通知 |
よくある間違い
- 全てをDirect Referenceで済ませる: 初期は楽ですが、プロジェクトが大きくなると修正コストが爆発的に増大します。汎用的な機能にはInterfaceを使いましょう。
- Interfaceのメッセージを実装し忘れる: Interfaceを実装したのに、対応する
Eventノードをイベントグラフに配置し忘れると、メッセージは無視されます。 - Event Dispatcherのアンバインド忘れ: アクターが破棄される際にアンバインドしないと、存在しないアクターにイベントが送られ続け、パフォーマンス低下や予期せぬエラーの原因になります。
通信方法の選択指針
Unreal EngineのBlueprintにおける通信方法は、ゲームの設計思想そのものです。
- Direct Reference は、手軽な個別会話。
- Interface は、共通のルールに基づいたビジネス会話。
- Event Dispatcher は、不特定多数へのニュース速報。
これらの特性を理解し、適切な場面で使い分けることで、あなたのUnreal Engineプロジェクトはより堅牢で、拡張性の高いものになるでしょう。まずは小さなプロジェクトでInterfaceとEvent Dispatcherを試してみて、そのメリットを実感してください。