【Unreal Engine】Event Dispatcher入門:アイテム取得を知らせ、BindとUnbindを試す

作成: 2025-12-12最終更新: 2026-09-05

アイテムを拾うと、取得数と表示が別々に更新される仕組みを作ります。Event Dispatcherの作成・Bind・Call・Unbindを図解し、通知に渡す値、受信する期間、中央Dispatcherへの発展を解説。

アイテムを拾ったら、所持数を増やし、画面に知らせ、効果音も鳴らしたい。すべてをアイテムのBlueprintへ書くと、反応を追加するたびに、アイテムの取得処理も編集することになります。

Event Dispatcher を使うと、アイテムは「拾われた」と知らせ、それを受けた各担当が反応を決められます。ベルを鳴らす人と、その音を聴いて動く人を分けるイメージです。

他のエンジンでいうと: Godot の signal 、Unity の UnityEvent や C# の event に当たります。知らせる側が、受け取る側を知らなくてよい点も同じです。

今回は「ベルを作る・登録する・鳴らす」の順に組み、取得数と表示を更新します。さらに表示側だけ受信を止めて、通知を送る処理を変えずに、受け取り方を変えられる ことを確かめましょう。

ベルを鳴らす人形と、灯りのともる家。出来事を知らせ、受け手が反応するイメージ

この記事でわかること

  • Dispatcherの作成、受信登録のBind、通知を送るCall
  • 通知にアイテム名と個数を載せる方法
  • 1回の取得で、個数管理と表示を別々に動かす実践
  • Unbindで受信を止め、再びBindする方法

Sponsored

Event Dispatcher:出来事と反応を分ける

Dispatcherは、出来事を受け取るイベントの登録先です。アイテムに OnItemPickedUp というDispatcherを作り、取得したときに呼ぶと、登録しておいたイベントが動きます。

操作意味ベルに例えると
Dispatcherを作る通知の名前と、渡す値を決めるベルを用意する
Bindこの通知で動かすイベントを登録するどのベルを聴くか決める
Call登録されたイベントへ通知するベルを鳴らす
Unbind指定したイベントの登録を外すそのベルを聴くのをやめる
アイテムが各担当を直接呼ぶ方法と、取得したことをDispatcherで知らせる方法

アイテム側に、表示や音の具体的な処理を並べなくてよくなるのが利点です。新しい反応を同じ通知へ登録すれば、取得処理を直さずに追加できます。

ただし、つながりがなくなるわけではありません。受信登録には 発信元の個体を指す参照 が必要です。また、受け手は通知の名前と、渡される値の型を合わせます。こうして、相手の内部の作りに頼る部分を減らす設計を、疎結合と呼びます(→ 通信3方式の使い分け)。

実践:拾ったアイテムの数と表示を更新する

1個のアイテムに触れると、Gemを3個取得したことを通知します。それを個数管理と表示の2つのActorが受け取り、次の結果を出します。

受け取る担当起こること
BP_InventoryManagerTotalCountが0から3になり、Print Stringで確認できる
BP_PickupNoticeワールド内の文字がWaiting...からGem x3へ変わる

今回は、所持品一覧や専用HUDを作る前に、通知に載せた値が別々の担当へ届くかを試します。

ベルを作り、受け手が登録し、出来事が起きたら鳴らすという3段階

① 拾えるアイテムを用意する

アイテムを1回拾うと、同じ通知で取得数が0から3へ増え、表示がWaiting...からGem x3へ変わる

Third PersonのBlueprintプロジェクトを使います。Variantがある版はNoneにし、テンプレートの歩けるレベルを開きます。

Actorを親に BP_Item を作ります。ComponentsへSphere Collisionを追加し、DefaultSceneRootの上へドラッグしてRootにします。その子へStatic Meshを追加し、エンジン標準のSphereを選びます。

部品設定
Sphere CollisionSphere Radius:60、Collision Enabled:Query Only
Sphere Collisionの応答PawnだけOverlap、ほかはIgnore
Generate Overlap Eventsオン
Static MeshSphere、相対位置0、ScaleはXYZすべて0.4
MeshのCollision PresetsNoCollision
MeshのSimulate Physicsオフ

Sphere CollisionのCollision PresetsをCustomにすると、Collision Enabledと各チャンネルへの応答を設定できます。

標準Sphereが見つからなければ、アセット選択欄でShow Engine Contentを有効にし、EngineのBasicShapesから選びます。

Overlap は、相手を押し返す代わりに、領域の重なりを検出する仕組みです。プレイヤー側のCapsule ComponentもGenerate Overlap Eventsをオンにします。今回は球の見た目より少し広い範囲へ触れると拾えます。

Variablesへ次の2つを作り、Compileしてから既定値を入力します。

変数既定値
ItemIDNameGem
QuantityInteger3

ItemIDはアイテムを見分ける名前、Quantityは今回拾う個数です。Compile・保存し、レベルへBP_Itemを1個置きます。ActorのScaleは1、中心は床の表面から60cm上を目安にし、プレイヤー開始位置から500cmほど離します。開始時から重ならないようにしてください。

② ベルを作る:通知に載せる値を決める

BP_ItemのMy Blueprint → Event Dispatchersの「+」から、OnItemPickedUp を作ります。選択したDispatcherのDetails → Inputsへ、次の2つを追加します。

入力名受け手へ伝えること
ItemIDName何を拾ったか
QuantityInteger何個拾ったか

この Inputsは、通知を送るときに一緒に渡す値 です。先ほどの変数がアイテム自身の設定、DispatcherのInputsが通知に載せる項目、という違いがあります。

今回の受け手が必要なのは名前と個数なので、それだけを渡します。拾ったActorは後で消えますが、通知で受け取った値を使えば、消えたアイテムへ問い合わせ直す必要はありません。

③ 個数管理のActorを作り、受信登録する

Actorを親に BP_InventoryManager を作ります。見た目の部品は要りません。次の変数を追加します。

変数設定
TargetItemBP_ItemのObject ReferenceInstance Editableをオン
TotalCountInteger既定値0

Object Reference は、相手の個体を指す値です。Instance Editableをオンにすると、レベルへ置いたManagerのDetailsから相手を指定できます。

Event GraphでBeginPlayから、白い実行ピンのある Is Valid へつなぎ、Input ObjectにGet TargetItemを入れます。Is Validは、その相手が存在して使えるかを確認します。

Get TargetItemの青いピンから Bind Event to OnItemPickedUp を作り、Is Validの成功側をBindの白い入力へつなぎます。BindのTargetはTargetItemです。Is Not Valid側は何もしません。

Bindの 赤いEventピン からドラッグし、「Add Custom Event for Dispatcher」で HandleItemPickup を作ります。Dispatcherに合わせてItemIDとQuantityの入力を持つイベントが作られ、赤い線でBindへつながります。

これで「このアイテムの通知が来たら、HandleItemPickupを呼ぶ」という登録になります。白い線は登録を実行する順番、赤い線は登録するイベントを示しています。

TargetItemを通知元に指定し、HandleItemPickupの赤いEvent出力をBindのEvent入力へ接続する

図はIs Validの成功側から先を示しています。左上の「Is Validの成功から」は接続元の注記です。

④ 通知を受けたら、個数を足す

HandleItemPickupの白い出力からSet TotalCountへつなぎます。設定する値は、Integerの加算で Get TotalCount + イベントのQuantity にします。

HandleItemPickupで受けたQuantityと現在のTotalCountを足し、Set TotalCountへ結果を渡す

ここで使うのは、先ほどBindへつないだHandleItemPickupです。別のイベントを作り直す必要はありません。

Setの後ろへPrint Stringをつなぎ、Durationを10秒にします。文字列はAppendで、Aを TotalCount: 、Bを更新後のTotalCountのString変換にします。

これで3個という通知を受けたら、0に3を足して「TotalCount: 3」と表示できます。ここでは取得した総数だけを扱い、アイテム別の一覧はインベントリの記事へ進めます。

Compile・保存してManagerをレベルへ1個置き、DetailsのTarget Itemへ、配置済みのBP_Itemを指定します。参照の変数を作っただけでは相手は入りません。割り当てまで済ませます。

⑤ 表示担当も、同じ通知を受け取る

Actorを親に BP_PickupNotice を作り、Text Render Componentを追加して名前を NoticeText にします。Text Renderは、ワールド内に文字を表示する部品です。

Textを Waiting...、World Sizeを40、Text Render Colorを濃い青にします。Compile・保存してレベルへ置き、床から150cmほどの高さで、Play開始位置から読める向きに回転させます。文字の裏側を見ている場合は、Actorの向きを調整してください。

BP_PickupNoticeにも、BP_ItemのObject Reference型で TargetItem を作り、Instance EditableをオンにしてCompile・保存します。レベルのNoticeのDetailsから、Managerと同じBP_Itemを指定します。

Event GraphへCustom Event StartListening を作り、そこからManagerと同じ Is Valid → Bind Event to OnItemPickedUp を組みます。Input ObjectとTargetはGet TargetItemです。

Bindの赤いEventピンから HandleNotice を作ります。BeginPlayからは StartListening(Target: self) を呼びます。受信登録を名前付きの入口へまとめておくと、後で登録し直すときにも使えます。

HandleNoticeの白い出力から、NoticeTextの参照を使って Set Text を作ります。Targetは NoticeText で、Actorのselfではありません。Valueには、次のFormat Textの結果を入れます。

Format Textの設定・入力
Format{ItemID} x{Quantity}
ItemIDHandleNoticeで受けたItemID
QuantityHandleNoticeで受けたQuantity
Resultの接続先Set TextのValue

Format Text は、{名前} の部分へ値を差し込んで文字を作るノードです。Format欄へ入力すると対応するピンが増えます。Gemと3を受け取れば、結果は「Gem x3」になります。

HandleNoticeの値をFormat Textへ渡し、その結果でNoticeTextの文字を更新する。白い実行線は直接Set Textへつなぐ

この表示はManagerのTotalCountを読んでいません。アイテムから受け取った情報だけで表示できるので、2つの受信イベントのどちらが先に動くかに依存しません。

⑥ 拾った瞬間にベルを鳴らす

BP_Itemへ戻り、Sphere CollisionのDetails → Eventsから On Component Begin Overlap を追加します。

Other Actorから Cast To BP_ThirdPersonCharacter を作り、Overlapの白い実行出力もCastへつなぎます。Other Actorは領域に入ってきた相手、Castはその相手を指定Classとして扱えるかの確認です。今回はテンプレートの操作キャラクターに反応させます。

OverlapのOther ActorをCastのObjectへ渡し、成功側をDoOnceへつなぐ

Castの成功側から次の順につなぎます。Cast Failed側は何もしません。

  1. DoOnce。Start Closedはオフ、Resetは未接続。
  2. Call OnItemPickedUp。Targetはself、ItemIDへGet ItemID、QuantityへGet Quantityを渡す。
  3. Destroy Actor。Targetはself。
DoOnceのCompletedからCallへつなぎ、ItemIDとQuantityを通知してからDestroy Actorを呼ぶ

DoOnceで取得を1回にし、通知を送ってから、アイテムを消します。Callでは、取得数を足す処理や文字を変える処理を直接呼んでいません。それらは登録した側が受け持ちます。

⑦ 拾った結果を確認する

3つのBlueprintをCompile・保存してPlayします。ゲーム画面をクリックし、歩いてアイテムへ近づきます。

状態期待する結果
拾う前アイテムが見え、表示はWaiting...
球へ触れるアイテムが消え、TotalCount: 3と出る
同じ取得の通知NoticeTextがGem x3へ変わる
その場所をもう一度通る追加の取得は起きない

何も起きなければ、Overlap直後のPrintで重なりを検出できているか確認します。アイテムは消えるのに反応がなければ、各TargetItemの割り当て、BeginPlayからBindまでの白線、赤いEvent接続を見ます。

Printは出るのに文字が変わらない場合は、Notice側のBindとSet TextのTargetを調べます。エディタで文字も見えないなら、まず向き・位置・World Sizeを確認してください。

次にPlayを止め、BP_ItemのQuantityを5へ変えてみます。再び拾うとTotalCount: 5、Gem x5になれば、通知に載せた値を両方が使えています。確認後はQuantityを3へ戻します。

Sponsored

Unbind:表示側だけ、受信を止めてみる

表示の監視をやめたい、別の相手を表示したい。そんなときに、今までの通知を受け取る登録を Unbind で外します。Actorを消さなくても、受信だけを止められます。

表示側だけUnbindすると、取得数は0から3へ増える一方、文字はWaiting...のままになる

同じイベントの登録を外す

BP_PickupNoticeの同じEvent Graphへ、Custom Event StopListening を追加します。

  1. StopListeningからIs Validへつなぎ、Input ObjectにGet TargetItemを入れる。
  2. Get TargetItemから Unbind Event from OnItemPickedUp を作る。
  3. Is Validの成功側をUnbindの白い入力へつなぐ。TargetはTargetItem。
  4. すでに作ったHandleNoticeの赤いEvent出力 を、Unbindの赤いEvent入力へもつなぐ。

新しい同名イベントを作るのではなく、登録したのと同じHandleNoticeを指定します。赤い出力からBindとUnbindの2か所へ線を伸ばして構いません。Unbind側のIs Not Validは何もしません。

登録済みHandleNoticeの赤いEvent出力を、同じTargetItemのUnbindへ接続する

図では解除に使う線だけを示しています。HandleNoticeからSet Textへつないだ白線や値の線は、そのまま残してください。

Uで止め、Bで登録し直す

レベルに置いたBP_PickupNoticeを選び、Level Blueprintで右クリック →「Create a reference to[名前]」を選びます。その参照から、次の呼び出しを作ります。

キーのPressed呼ぶCustom EventTarget
UStopListening配置したBP_PickupNotice
BStartListening同じBP_PickupNotice

Compile・保存して、次の2回を別々のPlayで試します。

操作個数管理文字表示
拾う前にUを押し、その後に拾うTotalCount: 3Waiting...のまま
新しくPlayし、拾う前にU→Bを押してから拾うTotalCount: 3Gem x3

アイテムの取得処理を変えず、表示側の反応だけを止めたり戻したりできました。Manager側はUnbindしていないため、どちらも取得数を受け取ります。

最初の試験で拾った後にBを押しても、過去の通知は再送されません。今回はアイテム自体も消えているので、StartListening内のIs Validで止まります。やり直すときは、Stopして新しくPlayしてください。

解除の目的は「いつまで受け取るか」を決めること

例えば、UIが監視するアイテムをAからBへ替えるときは、Aの通知をUnbindしてから、BへBindします。Aがまだ存在していても、古い相手の通知で表示が変わるのは困るためです。

また、WidgetをRemove from Parentで画面から外すことと、そのWidgetのオブジェクトが消えることは同じではありません。画面を閉じたら受信も止めたいなら、その場面で解除する形を考えます。

BlueprintのDispatcherについて「Unbindしないと、必ず破棄済みの相手へ届いてクラッシュする」と覚える必要はありません。その相手の通知を、今も受け取りたいか を基準に、登録と解除の場所を決めます。

Sponsored

おまけ:先に知っておくと良いこと

受信者を増やすときは、アイテムを直さなくてよい

例えば音の担当を追加するなら、新しいActorで同じTargetItemへBindし、受信イベントからPlay Sound 2Dで用意した効果音を再生できます。BP_ItemのCallはそのままです。

実際の所持品一覧やHUDも、今回の個数管理・文字表示と同じ場所へ反応を追加できます(→ インベントリUMG)。

通知の順番を前提にしない

複数の受信イベントが、Bindした順番どおりに動くとは限りません。今回のNoticeは通知のItemIDとQuantityを直接使い、Managerの処理が終わるのを待つ必要がない形にしました。

「まず所持数を更新し、その確定値をUIへ知らせたい」なら、所持数を管理する側が更新を終えてから、その値を載せた別の通知を送ると順序が明確になります。

同じBindを繰り返したら?

同じDispatcherへ同じイベントを繰り返しBindしても、登録は1つです。反応が2回出るときは、別の受信イベントも登録していないか、発信側のCallが2回実行されていないかを調べます。

今回のDoOnceは発信回数を1回にするためのものです。Bindの重複対策とは役割が違います。

Unbind Allは、ほかの受信者も外す

Unbind Eventは指定したイベントを外します。Unbind Allは、そのDispatcherの登録をまとめて外します。今回の表示だけを止める操作でUnbind Allを使うと、Managerの受信まで外してしまいます。

アイテムが増えたら、通知の置き場所を考える

今は1個のアイテムを、2つの担当から指定しました。実行中に多数のアイテムが生まれるゲームでは、すべてへ個別に登録するより、取得情報をまとめる担当へ通知を集める方法があります。

各アイテムの出来事をGameStateなどの共通の発信元へ集め、受け手はそこへ登録する

例えば1つのレベル内なら、GameStateや所持品を管理するComponentへOnAnyItemPickedUpを置き、アイテムはそちらへ情報を渡します。UIは個々のアイテムではなく、その共通の発信元へBindします。

GameStateとGameInstanceでは存続する範囲が違います。「誰もが知っている場所」だけでなく、その情報をいつまで使うか も考えて選びます(→ Game FrameworkComponentの再利用)。

通知の名前は、起きたことを表す

OnItemPickedUp、OnHealthChangedのように出来事を名前にすると、表示・音・実績などが同じ通知を使いやすくなります。UpdateUIのように特定の反応を名前にすると、その用途専用の入口に見えます。

なお、UMGのButtonで使うOnClickedも、押されたことを知らせる同じ仲間です。自作Dispatcherも、受け手に反応を登録するという点では身近な仕組みです。

C++との対応を知りたい人へ

BlueprintのEvent Dispatcherに対応するC++の仕組みは、ダイナミック・マルチキャストデリゲート です。「複数の受け手の処理を登録し、まとめて呼べるもの」と捉えるところから始められます。

BlueprintのDispatcher操作と、C++のデリゲート側の名前の対応
Blueprint側の操作C++側で使うもの
Dispatcherの定義DECLARE_DYNAMIC_MULTICAST_DELEGATE系の宣言
Blueprintへ公開UPROPERTYのBlueprintAssignable
BindAddDynamic
CallBroadcast
UnbindRemoveDynamic

本記事の実践にC++は必要ありません。C++側から通知を公開したくなったら、BlueprintからC++への第一歩と、公式のDynamic Delegatesへ進めます。

まとめ

BP_ItemのOnItemPickedUpへ、個数管理と表示を登録しました。アイテムは名前と個数を知らせ、受け手がそれぞれ加算と表示を行います。表示だけをUnbindしても、アイテムと個数管理は同じように動きました。

通知を作るときは、「何が起きたか」「どの値を渡すか」「誰がいつまで受け取るか」を揃えると、処理の分担を追いやすくなります。相手へ共通の操作を頼む方法は、Blueprint Interfaceで扱います。

参考リンク

Unreal Engine このセクションのノート98