【Unreal Engine】Blueprint Interface入門:敵にも箱にも、同じ呼び方でダメージを渡す

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

Blueprint Interfaceで、敵と箱へ同じメッセージを送り、HPを減らしてみます。Target・実装・引数の意味、Castとの使い分け、Reference Viewerで参照関係を調べる方法まで図解します。

攻撃が当たった相手が敵ならHPを減らす。木箱なら壊す。対象が増えるたびに「敵か? 箱か? タワーか?」とCastを並べていると、攻撃側にも相手の種類を追加し続けることになります。

Blueprint Interface を使うと、相手へ「この量のダメージを受けてください」と同じ呼び方で頼めます。どう反応するかは、受け取った側が決めます。新しい対象を追加しても、攻撃側の呼び出しを増やさずに済む仕組みです。

この記事では、敵と箱のHPを実際に減らしてから、Castとの違いや参照関係の調べ方へ進みます。通信3方式の使い分けで紹介したInterfaceを、自分で作って使うための実践です。

特定の相手へつながる鎖を切り、共通の呼びかけへ置き換えるイメージ

この記事でわかること

  • Interfaceに決めることと、受け手に作る処理の違い
  • 同じMessageノードで、敵と箱のHPを減らす方法
  • Targetの指定と、未対応の相手に送ったときの動き
  • Castの使い分けと、Reference Viewerで確認できること

Sponsored

Interfaceは、共通の依頼書

敵と箱では、見た目も役割も違います。それでも「ダメージを受ける」という入口をそろえれば、攻撃側はどちらにも同じように頼めます。

Interfaceには、その入口の 名前と、受け渡す値 を決めます。今回は ReceiveWeaponHit という名前で、ダメージ量を渡すことにします。

担当今回決めること
BPI_DamageableReceiveWeaponHitという機能に、DamageAmountという小数値を渡す
敵・箱ReceiveWeaponHitを受けたら、自分のHPを減らす
攻撃側対象を指定し、ReceiveWeaponHitで25を渡す

実装する とは、入口の先に実際の処理を書くことです。Interfaceは依頼書なので、HPを保管する変数や、HPを減らす処理は持ちません。その中身は敵や箱のBlueprintへ作ります。

BPI_Damageableには共通の入口と引数を決め、敵と箱がそれぞれ自分のHealthを減らす処理を実装する

呼び出すときには、Targetという宛先が必要 です。同じMessageノードを使えても、1回の呼び出しで処理するのは指定した相手です。周囲の敵や箱へ一斉に届くわけではありません。

実践:敵と箱へ25ダメージを渡す

Fキーで、指定したActorへ25ダメージを渡す小さな実験を作ります。敵を指定するとHP100→75、箱を指定すると30→5。相手を変えても、送る側のグラフは同じ という点を確かめます。

1回目のPlayでは敵に25を送り100から75へ。相手を箱へ替えて次のPlayでは30から5へ

UE5のThird PersonテンプレートをBlueprintで作り、VariantがあればNoneを選びます。新しい練習用フォルダへ作れば、既存記事の同名Blueprintと混ざりません。変数の作成とGet・Setは変数の基礎が前提です。

今回はHPの変化をPrint Stringで確認します。攻撃アニメーションや死亡演出は付けず、HPが0になってもActorは残します。

① 依頼書を作る

コンテンツブラウザで右クリック →「Blueprints」→「Blueprint Interface」を選び、BPI_Damageable を作ります。

  1. 開いたときの関数名を ReceiveWeaponHit に変える。
  2. その関数のDetails → Inputsへ DamageAmount を追加し、型をFloatにする。
  3. Outputsは空のままにし、Compile・保存する。

Float は25や12.5などの小数を扱う型です。DamageAmountは、呼び出すときに渡す 引数 で、「今回いくつHPを減らすか」を表します。

ここでHPを減らすノードを置けないのは正常です。依頼の形式ができたので、次に受け手の処理を作ります。

② 敵と箱のActorを用意する

「Blueprint Class」→「Actor」から、BP_EnemyBP_Crate をそれぞれ作ります。どちらも親はActorで、別々のClassにします。

設定BP_EnemyBP_Crate
追加する部品Static MeshStatic Mesh
メッシュエンジン標準のCylinderエンジン標準のCube
変数Health、FloatHealth、Float
Healthの既定値10030

メッシュが見つからなければ、アセット選択のSettingsで「Show Engine Content」をオンにし、Engine/BasicShapes のものを使います。部品の位置・回転は0、Scaleは1、Simulate Physicsはオフにします。

変数を追加したらCompileし、Healthの既定値を入力します。保存して両方をレベルへ置き、ActorのScaleは1、中心が床から50cm程度の位置にします。操作キャラクターから見やすい場所へ並べれば十分です。

次に両方のBlueprintを開き、「Class Settings」→「Interfaces」の追加欄から BPI_Damageable を選び、Compileします。

これで「このClassはReceiveWeaponHitに対応する」と宣言できました。まだHPを減らす処理はないので、続けて実装します。

③ 受け取った量だけ、自分のHPを減らす

BP_EnemyのEvent Graphで右クリックし、Interfaceの Event ReceiveWeaponHit を追加します。同じ名前のCustom Eventを新しく作るのではなく、追加したInterfaceのイベントを選んでください。

Event ReceiveWeaponHitには、白い実行出力とDamageAmountの値の出力があります。次のようにつなぎます。

  1. 白い実行出力をSet Healthへつなぐ。
  2. Floatの減算を作り、AにGet Health、BにイベントのDamageAmountをつなぐ。
  3. 減算の結果をFloatのMaxへ入れ、もう一方を0にする。
  4. Maxの結果をSet Healthの値へつなぐ。
Get Healthを減算のA、受信したDamageAmountをBへ渡し、Maxで0以上にしてSet Healthへつなぐ

Max は、2つの値の大きい方を返すノードです。HPが5のときに25を引くと−20ですが、0と比べて大きい方を選ぶので、HPは0で止まります。この練習では正のダメージ量だけを送ります。

Set Healthの後ろへPrint Stringをつなぎ、Durationを10秒にします。AppendのAを Enemy HP: 、Bを 更新後のGet HealthをStringへ変換した値 にし、結果をPrintのIn Stringへ渡します。

Set Healthの実行出力からPrintへ。更新後のHealthをTo StringとAppendで表示用の文字列にする

図の「Set Healthの実行出力から」は、前の図とのつなぎ目を示す注記です。To String(Float)は数値を文字列にし、Appendは前後の文字列を連結します。

BP_Crateにも同じ処理を作り、AppendのAだけ Crate HP: にします。Compile・保存してください。敵と箱はそれぞれ自分のHealthを持つので、箱へのダメージで敵のHPが減ることはありません。

④ 相手を指定して、Messageを送る

Actorを親に BP_DamageSender を作ります。送信を担当するだけなので、見た目の部品は不要です。

変数 TargetActor を作り、型を ActorのObject Reference、Instance Editableをオンにします。Object Referenceは、レベルにいる相手の個体を指定する値です。ここではBP_Enemy専用の型にせず、箱も受け取れるActor型にします。

Event GraphへCustom Event SendHit を作り、次をつなぎます。

  1. SendHitから、白い実行ピンのあるIs Validへつなぐ。
  2. Is ValidのInput ObjectにGet TargetActorを入れる。
  3. Get TargetActorの青いピンからドラッグし、ReceiveWeaponHit(Message) を検索して置く。
  4. Is Validの成功側をMessageの白い入力へつなぎ、Damage Amountを25にする。TargetはGet TargetActor。

封筒アイコン付きのMessageノード を選びます。BP_DamageSender自身にInterfaceを追加する必要はありません。受け取る敵と箱が実装していれば呼べます。

Is Validは、相手が存在して使えるかの確認です。Is Not Valid側にはPrint Stringで Target is not set を10秒表示し、宛先の指定忘れが分かるようにします。

SendHitからIs Validを通り、TargetActorへReceiveWeaponHitのMessageを送る。相手が未設定ならPrintで知らせる

Compile・保存し、BP_DamageSenderをレベルへ1個置きます。そのActorのDetailsにあるTarget Actorへ、配置したBP_Enemy を指定します。変数を作っただけでは相手は入りません。

最後に、配置したBP_DamageSenderを選んだままLevel Blueprintを開きます。右クリック →「Create a reference to[名前]」で参照を作り、その青い出力からSendHitを呼びます。FキーのPressedをSendHitの白い入力へつなぎます。

FのPressedからSendHitを呼び、Targetにはレベルに配置したBP_DamageSenderの参照を渡す

Fキーはこの練習の入力なので、Level Blueprintで受けます。BP_DamageSenderのAuto Receive Inputを変更する必要はありません。

⑤ 相手を変えても、同じ呼び出しが使えるか確かめる

Compile・保存してPlayし、ゲーム画面をクリックしてからFを1回押します。画面に Enemy HP: 75 と出れば、送った25が敵へ届いています。

Playを止め、レベルのBP_DamageSenderのTarget Actorを、配置したBP_Crateへ変えます。グラフは編集せず、再びPlayしてFを押してください。

操作期待する表示
敵を指定して、新しくPlay→FEnemy HP: 75
箱を指定して、新しくPlay→FCrate HP: 5
同じPlayで、もう一度FCrate HP: 0
さらにFCrate HP: 0。負の値にはならない

相手を差し替えるだけで、同じReceiveWeaponHitから別々のClassの処理を呼べました。送る側は敵のHealthも箱のHealthも直接書き換えず、ダメージ量だけを渡しています。

次は、レベルへ普通のCubeを置き、Target ActorをそのCubeにして試します。このCubeにはBPI_Damageableを追加していないので、Fを押してもHPの表示は出ません。Messageは、Interface未対応の相手では処理を呼びません。

Cube自体は存在するため、Is Validは成功します。「存在する」と「その依頼に対応している」は別の確認だと分かります。確認後はTarget Actorを敵へ戻してください。

ダメージ量も変えたいなら、Messageの25を40へ変えて、新しいPlayで敵に送ります。100→60になれば、受信側が固定の25ではなく引数を使えています。確認後は25へ戻します。

Sponsored

Castとハードリファレンスを分けて考える

Cast は、参照している相手を、指定したClassとして扱えるか調べるものです。成功すれば、そのClass固有の変数や関数を使えます。別のActorを生成したり、箱を敵へ作り変えたりする処理ではありません。

他のエンジンでいうと: C# の as / is 、GDScript の as に近い「型を確かめて、その型として扱う」操作です。 GetComponent<T>() のような 部品の取得とは別物 です。

たとえば敵専用の攻撃パターンを変更したいなら、BP_Enemyとして扱う必要があります。一方、今回のように「ダメージを受ける」という共通機能だけが必要なら、相手ごとにCastを並べずInterfaceで頼めます。

ここに、もう一つ別の話として アセットの依存関係 があります。依存とは「自分が動くために、別のアセットも必要」というつながりです。

Cast To BP_Enemy を置いたBlueprintは、BP_EnemyというBlueprintアセットへの ハードリファレンス を持ちます。これは、参照元を読み込むときに参照先も必要になるつながりです。BP_Enemyがさらにメッシュや音をハード参照していれば、その先へ読み込みが連なります。

そのため、今は必要ない敵や装備のBlueprintまで広く参照していると、読み込みやメモリ使用の負担につながることがあります。これは Castを1回実行する時間 と、参照先のアセットを読み込む負担 を分けて考える話です。「Castがあるから遅い」とは判断できません。

Interfaceにすると、送信側は具体的なBP_Enemyの代わりに、共通のBPI_Damageableを使えます。ただし依存がゼロになるわけではありません。Interface自身への参照や、ほかの変数・ノードに残った参照もあるため、次の方法で確かめます。

具体的な敵Blueprintを参照する経路と、共通のInterfaceを参照する経路の比較。ほかの参照経路も確認する

ハード参照と、必要になったときに読み込めるソフト参照の違いは、アセット管理の基礎でも紹介しています。

Reference Viewerで、依存する相手を確かめる

Reference Viewer は、アセット同士の「どれが、どれを使うか」を見る道具です。グラフが短くなったかだけでなく、送信側が敵の種類を直接知る必要がなくなったかを調べられます。

  1. BP_DamageSenderをCompile・保存する。
  2. コンテンツブラウザでそのアセットを右クリックし、「Reference Viewer」を開く。
  3. 中央のBP_DamageSenderから、右側の依存先を確認する。
  4. BPI_Damageableへの参照を探し、BP_EnemyやBP_Crateへ直接依存する経路がないかを見る。

調べるのは BP_DamageSenderアセット です。レベル全体を開くと、そこへ置いた敵や箱の参照も出るので、別の調査になります。今回のTarget Actorの割り当ては、レベルに置いたSenderの個体に対して行っています。

自分の既存グラフをCast版から変更する場合は、変更前の画面を残して比べます。「View」の参照種別や検索の深さ・表示数をそろえ、同じ条件で更新してください。フィルタで隠れた線を、消えた依存と取り違えないようにします。

BP_Enemyへの参照が残っていたら、BP_Enemy型の変数、ほかのCast、Classを指定するノードなどを探します。Messageへ1か所置き換えるだけで、別経路の参照まで消えるわけではありません。

Cast版はBP_EnemyとBP_Crateへ直接依存するが、Interface版はBPI_Damageableだけを見る

サイズの内訳を見たいときは、同じアセットを右クリック →「Size Map」を開きます。アセットと依存先のサイズを図で確認できます。比較するならDisk Size/Memory Sizeなどの表示条件をそろえ、大きな割合を占める参照先を調べます。

Reference Viewerの線は依存関係、Size Mapはサイズを見るものです。線が3本減ったから何秒速くなった、とは分かりません。 実際の読み込み時間は、別の参照経路や、すでに読み込まれているアセットなどにも左右されます。速度の改善を確かめたい段階では、Unreal Insightsなどで同じ条件の実行を計測します。

呼んでも動かないときに見るところ

症状確認するところ
Target is not setと出るレベルのSenderに、配置済みActorを割り当てたか
相手はいるのにHPが出ない相手のClass SettingsへBPI_Damageableを追加したか
Interfaceは追加済みEvent ReceiveWeaponHitから、白い線がSet HealthやPrintへ続いているか
40を送っても25しか減らない減算のBに、イベントのDamageAmountを使っているか
Messageが見つからないBPIをCompile・保存し、Actorの青い参照ピンから検索したか
別の相手が反応するMessageのTargetが、今回処理したい個体を指しているか

未対応の相手では何も起きないため、送信側から見るだけでは実装忘れに気付きにくいことがあります。迷ったら、受信側のEvent ReceiveWeaponHit直後へ一時的にPrintを置き、まず届いているかを調べると切り分けやすくなります。

Does Implement Interface は、相手がそのInterfaceに対応するかを返す判定です。Test Objectへ相手の参照、InterfaceへBPI_Damageableを指定すると、結果がBooleanで返ります。BooleanはTrue/Falseの2通りの値です。

Does Implement Interfaceで対応の有無を調べ、結果に応じて次の処理を選ぶ

これはMessageの前に必ず挟むものではありません。「対応している相手だけ照準を変える」「未対応なら別の案内を出す」のように、対応の有無で処理を選びたいとき に使います。単に対応する相手へ依頼を送るだけなら、今回のMessageで足ります。

Sponsored

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

攻撃の当たり判定とつなぐ

今回のTargetActorは手で割り当てましたが、実際の攻撃では、Line TraceのHit Actorや、弾が重なったOther ActorをMessageのTargetへ渡します。「相手を見つける処理」と「見つけた相手へ頼む処理」を分けておくと、剣でも弾でも同じ入口を使えます。

標準の Apply DamageEvent AnyDamage でもダメージを扱えます。ここで作ったReceiveWeaponHitはInterfaceを学ぶための独自機能で、標準のダメージイベントを自動的に呼ぶものではありません。標準機能を使う実践は体力とダメージの記事へ進めます。

体力Componentと組み合わせる

体力Componentの記事のBP_HealthComponentを使うなら、ActorのEvent ReceiveWeaponHitから、部品の ApplyHealthDamage を呼びます。Targetに自分のHealthComponent参照、Damage Amountに受け取ったDamageAmountを渡します。

その場合、この記事のActor側のHealth変数と減算は部品の処理へ置き換えます。Interfaceが「ダメージの入口」、Componentが「体力の保管と計算」という分担です。部品を追加するだけで、Actor宛てのMessageが自動転送されるわけではありません。

Interfaceにも戻り値を定義できる

今回は依頼を送るだけなのでOutputsを空にしました。たとえば GetInteractionText にText型の戻り値を付ければ、対象ごとに「開ける」「調べる」などの表示文字を返せます。戻り値を持つ場合は、受信側では関数として中身を実装します。

ただし、Messageの相手が未対応なら処理は実行されません。戻った値だけで対応済みと判断せず、必要な場面ではDoes Implement Interfaceも使います。

依頼書には、受け渡しに必要な型を選ぶ

Interfaceの入力をBP_Enemy専用の参照型にすると、依頼書自体がそのBlueprintを知る必要があります。今回ならFloatのダメージ量だけで十分です。種類を問わない相手の参照が必要ならActor型を検討するなど、具体的なClassを使う理由があるか考えます。

C++でも、入口と実装を分けられる

C++ではUInterfaceを使って共通の入口を定義できます。最初からC++へ移す必要はなく、Blueprintで役割が分かってからBlueprintからC++への第一歩へ進めば十分です。

まとめ:CastとInterfaceの使い分け

やりたいこと選び方
そのClass固有の変数や関数を使いたいCastで指定Classとして扱えるか確認する
種類の違う相手へ、共通の機能を頼みたいInterfaceで入口と受け渡す値をそろえる
出来事を複数の受け手へ知らせたいEvent Dispatcherへの登録と通知を使う

敵と箱で試したように、Interfaceを使うと送信側は「誰の内部をどう変えるか」まで決めず、共通の依頼を渡せます。受け手を追加するときは、Interfaceの追加と、そのActorらしい反応を用意します。

参照関係を調べるときも、Castの数だけを減らすことを目標にせず、必要な相手へつながっているかを確認してください。出来事を複数の担当へ知らせる仕組みは、Event Dispatcherの記事で試せます。

参考リンク

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