【Unreal Engine】Blueprint Component入門:体力の部品を敵と木箱で使い回す

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

敵と木箱に同じ体力Componentを追加し、25ダメージでHP100・30がどう減るかを確認します。ActorComponentとSceneComponent、Owner、関数とEvent Dispatcherの役割を図と実践で解説。

敵にも、壊せる木箱にも、砦のタワーにも体力を持たせたい。3つのBlueprintへ同じ体力処理をコピーすれば動きますが、ダメージの計算を変えるたびに、3か所を直すことになります。

そんなときに使えるのが、自作のBlueprint Component です。体力の計算を「差し込む部品」として1回作り、必要なActorへ追加します。敵と木箱を同じ専用の親クラスに揃えなくても、同じ機能を使えます。

今回は、体力100の敵役と、体力30の箱へ同じ部品を付けます。25ずつ減らす操作を用意し、残りHPと、力尽きたときの反応を見ながら、共通にする部分と各Actorへ任せる部分を整理しましょう。

ハートの付いた部品を、違う形の本体へ差し込む人形。Componentを使った機能の再利用

この記事でわかること

  • Actorへ同じ機能を追加して使い回す考え方
  • ActorComponentとSceneComponentの違い
  • 体力を減らす関数と、変化を知らせるDispatcherの作り方
  • 敵と箱で同じ計算を使い、異なる反応を返す実践

Sponsored

Blueprint Component:Actorへ足す機能の部品

Static Mesh Componentが見た目を、Projectile Movement Componentが弾の移動を受け持つように、ComponentはActorへ機能を追加するための部品です。見た目だけでなく、体力や所持品を管理する部品もBlueprintで作れます(→ ActorとComponentの基本)。

他のエンジンでいうと: Unity の Component とほぼ同じ考え方です。Godot では、機能ごとに 子Node を足す形が近くなります。

同じHealth Componentの設計を、敵・木箱・タワーへ追加して使う

例えばBP_HealthComponentを敵と箱へ1個ずつ追加すると、体力の計算方法は共通でも、現在のHPは別々 に持ちます。箱がダメージを受けても、敵のHPまで減るわけではありません。

Componentを取り付けた本体のActorを Owner と呼びます。敵へ付けた部品のOwnerは敵、箱へ付けた部品のOwnerは箱です。Component単体を、Actorのようにレベルへ置いて使うのではありません。

比べることActorComponent
今回の役割敵役や箱という本体体力を管理する部品
使い始める場所レベルへ配置するActorのComponentsへ追加する
共通にする範囲本体全体の設計体力など、必要な機能のまとまり

位置を持つ部品か、持たない部品か

Componentを自作するときは、まず親クラスを選びます。ここでいう Transform は、位置・回転・大きさをまとめたものです。

親クラス部品自身のTransform向いている例
ActorComponent持たない体力、所持品、状態の管理
SceneComponent持つ銃口の位置、エフェクトを出す基準点

体力の計算には、部品自身の位置が要らないのでActorComponentを使います。敵がどこへ移動しても「HPから25を引く」という仕事は変わりません。

SceneComponentは、親から見た位置や向きを持てる部品です。ただし、SceneComponentそのものに見た目や当たり判定があるわけではありません。描画ならStatic Mesh、箱型の当たり判定ならBox Collisionなど、それぞれの機能を持つ派生Componentを使います。

HPを計算するActorComponentと、位置・回転・大きさを持つSceneComponent。どちらもActorへ追加する部品
Sponsored

実践:体力の部品を敵と箱へ付ける

まず、Fキーで敵役へ25ダメージ、Gキーで箱へ25ダメージを与えます。弾やHPバーを作る前に、部品へ頼んだ計算と通知が動くかをPrint Stringで確かめます。

到達点は、敵役が 100→75→50→25→0、箱が 30→5→0 と減り、それぞれのActorが力尽きたときの反応を決める状態です。

Fキーで敵役を25ずつ減らして非表示にし、Gキーで箱を25ずつ減らして削除する

① 体力Componentを作る

Content Browserで「Blueprint Class」を作り、親クラスをActorComponent、名前を BP_HealthComponent にします。親が一覧に見えない場合は「All Classes」でActorComponentを検索します。

Variablesへ次の2つを作り、Compile後に既定値を設定します。

変数既定値設定・用途
MaxHealthFloat100.0Instance Editableをオン。取り付け先で最大HPを変える
CurrentHealthFloat0.0現在のHP。Component内で更新する

Instance Editableは、同じ部品でも取り付けた個体ごとに値を変えられる設定です。今回はMaxHealthへ100または30を入れ、0より大きい値で使います。

ComponentのEvent Graphで Event BeginPlay → Set CurrentHealth をつなぎ、値へGet MaxHealthを入れます。開始時に、その個体の最大HPで満タンにします。

② 変化を知らせる出口を作る

My BlueprintのEvent Dispatchersの「+」から、次を作ります。

Dispatcher名DetailsのInputsへ追加する値知らせること
OnHealthChangedNewHealth:FloatHPを更新したことと、新しい値
OnDiedなしHPが0になったこと

Event Dispatcher は、出来事を、それを受け取るように設定した相手へ知らせる仕組みです。Componentは「HPが0になった」と知らせ、敵や箱が「その後どうするか」を決めます。

通知を送る操作が Call、受け取るイベントを登録する操作が Bind です。名前を作るだけでは通知も反応も起きないので、送る側と受け取る側を順に組みます。

③ ダメージを受け付ける関数を作る

Functionsから ApplyHealthDamage を作り、Pureはオフ、InputsへFloatの DamageAmount を追加します。これは今回作る独自の関数です。UE標準の Apply Damage ノードとは別なので、名前を区別しておきます。

最初に「現在のHPが0より大きい」かつ「ダメージが0より大きい」を調べます。

  1. Floatの > でCurrentHealthと0.0を比べる。
  2. もう1個の > でDamageAmountと0.0を比べる。
  3. 2つの結果を AND Boolean へ入れ、その結果をBranchのConditionへつなぐ。
  4. 関数の入口からBranchへ白い実行線をつなぎ、True側だけを次の処理へ進める。False側はそのまま終える。

ANDは両方の条件を満たすときだけtrueになります。これで、HPが尽きた後の呼び出しや、0・負数のダメージは処理しません。

CurrentHealthとDamageAmountがそれぞれ0より大きいかをANDで合わせ、BranchのTrue側だけ進む

図のGet DamageAmountは、この関数へ渡された入力を読むノードです。関数内の右クリック検索から置くか、入口のDamageAmount出力を使えます。同じ名前のClass変数を新しく作る必要はありません。

True側へSet CurrentHealthを置きます。値は次の順で計算します。

ノード・入力渡す値
Floatの減算 - のAGet CurrentHealth
減算のB関数入力のDamageAmount
Clamp (Float)のValue減算の結果
ClampのMin / Max0.0 / Get MaxHealth
Set CurrentHealthの値Clampの結果

Clamp は、値を指定した範囲へ収めるノードです。箱のHPが5のときに25ダメージを受けても、-20ではなく0になります。減算とClampには白い実行線をつながず、値の線だけを使います。

CurrentHealthからDamageAmountを引き、Clampで0からMaxHealthの範囲へ収めた値をSet CurrentHealthへ渡す

Set CurrentHealthの白い出力から、次の順につなぎます。

  1. Call OnHealthChanged。NewHealthへ、更新後のCurrentHealthを渡す。
  2. CurrentHealth <= 0.0 をConditionにしたBranch。
  3. True側から Call OnDied。False側はそのまま終える。

各DispatcherをMy Blueprintからグラフへドラッグして「Call」を選べます。TargetはこのComponent自身のselfです。表示へ渡す値は、もう一度減算した結果ではなく、Setで更新した後のCurrentHealth を使います。

更新後のCurrentHealthをOnHealthChangedで送り、0以下ならOnDiedも呼ぶ

これで部品の仕事は「受け付けてよいか確認する→HPを更新する→変化を知らせる」となりました。敵の見た目や、箱が壊れる演出は、ここへ書きません。

④ 敵役と箱へ取り付ける

動作を試すレベルは、Third PersonのBlueprintプロジェクトで用意できます。Variantがある版はNoneを使います。Actorを親にした BP_EnemyBP_Crate を別々に作り、次の見た目を追加します。

ActorStatic Meshの例BP_HealthComponentのMaxHealth
BP_Enemyエンジン標準のCylinder100.0
BP_Crateエンジン標準のCube30.0

今回は敵のAIや木箱の素材は不要です。形の違う2つの本体で、同じ部品を使えるかを確かめます。メッシュが見つからない場合は、アセット選択欄でShow Engine Contentを有効にし、EngineのBasicShapesから選びます。

それぞれのActorのComponentsで「Add」からBP_HealthComponentを1個追加します。追加した部品を選び、DetailsでMaxHealthを表の値に設定してCompile・保存します。2つのActorを、Play開始位置から見える床の上へ並べて置きます。

⑤ Actor側でHPの通知を受け取る

まずBP_EnemyのEvent Graphを開きます。Componentsから追加した体力部品をドラッグして参照を置き、そのピンから Bind Event to OnHealthChanged を作ります。

Event BeginPlayをBindの白い実行入力へつなぎます。Bindの赤いEventピンからドラッグしてCustom Eventを作り、名前を HandleHealthChanged にします。Dispatcherに合わせたFloatのNewHealth入力が付きます。

このCustom Eventの後ろへPrint Stringを置きます。Append のAを Enemy HP: 、BをNewHealthのString変換にし、結果をPrint StringのIn Stringへ渡します。Durationは10秒にします。

箱にも同じ設定を行い、ラベルを Crate HP: に変えます。登録するBindはBeginPlayから、反応するPrintはCustom Eventから つなぎます。Bindの直後にPrintを置くと、HPが変わったときの反応にはなりません。

BeginPlayで体力ComponentのOnHealthChangedへHandleHealthChangedを登録し、通知時にCustom EventからPrintを実行する

この図は登録の接続を見せるため、NewHealthのString変換とAppendを省いています。HP表示は上の手順どおり、NewHealthから作った文字列をIn Stringへつないでください。

⑥ 力尽きたときの反応を分ける

同じ体力部品の参照から Bind Event to OnDied を作り、先ほどのBindの白い出力から続けます。赤いEventピンからCustom Eventを作り、名前を HandleDied にします。

各ActorのHandleDiedから、次を実行します。

Actor力尽きたときの処理
BP_EnemyPrint String「敵が倒れた」→ Set Actor Hidden In Game(true)→ Set Actor Enable Collision(false)
BP_CratePrint String「箱が壊れた」→ Destroy Actor

どちらもTargetはselfです。敵役は見えなくして当たり判定を止め、箱はActor自体を消します。実際の敵なら死亡アニメーション、箱なら破片の演出へ置き換えられます。

HPを減らす計算は共通、HPが0になった後は各Actorが決める。ここが、この部品を使い回すための分担です。

⑦ キーから部品へダメージを渡す

攻撃側は「敵Classか、箱Classか」を調べる代わりに、相手に体力Componentがあるか を調べます。今回は、Level Blueprintから2つのActorを指定して試します(→ Level Blueprintと配置Actorの参照)。

Level Blueprintを開き、Functionsへ DamageTarget を作ります。Pureはオフ、InputsへActorのObject Reference型で TargetActor を追加します。Object Referenceは、今回処理する相手の個体を指す値です。

関数内を次の順でつなぎます。

  1. 入口から、白い実行ピンのある Is Valid へつなぐ。Input ObjectはTargetActor。
  2. TargetActorから Get Component by Class を作り、Component ClassをBP_HealthComponentにする。
  3. 最初のIs Validの「Is Valid」側から、2個目のIs Validへつなぐ。そのInput ObjectはGet Component by ClassのReturn Value。
  4. 2個目の「Is Valid」側から、部品の ApplyHealthDamage を呼ぶ。Targetは同じReturn Value、DamageAmountは25.0。

Is Valid は、参照先が存在し、まだ使えるかを確かめます。最初の確認は「箱がすでに壊れていないか」、次の確認は「体力の部品を持っているか」です。どちらもIs Not Valid側は何もしません。

Get Component by Classは値を返すノードなので、白い実行線をつなぎません。Component Classを先にBP_HealthComponentへ指定すると、Return Valueから、その部品のApplyHealthDamageを呼び出せます。

DamageTargetの入力Actorが有効な場合に、BP_HealthComponentを調べる。Get Component by Classには実行線をつながない

Get TargetActorも関数入力を読むノードです。続く図は同じDamageTarget内の後半で、取得した部品を2個目のIs ValidとApplyHealthDamageの両方へ渡します。

取得したComponentが有効なら、それをTargetにしてApplyHealthDamageへ25を渡す

CompileしてEvent Graphへ戻り、FとGのキーイベントを作ります。それぞれPressedからDamageTargetを呼びます。

入力DamageTargetのTargetActor
FのPressedレベルに置いたBP_Enemyの参照
GのPressedレベルに置いたBP_Crateの参照

参照は、Outlinerで対象を選び、Level Blueprintの右クリックから「Create a reference to[名前]」で置けます。設計図ではなく、レベルへ置いた個体を選んでください。

⑧ HPの減り方と、共通の変更を確かめる

Component、両Actor、Level BlueprintをCompile・保存してPlayします。ゲーム画面をクリックしてから、キーを離して押す操作を繰り返します。

操作期待する結果
Fを1回ずつ、合計4回押すEnemy HPが75→50→25→0。4回目に「敵が倒れた」と出て姿が消える
Gを1回ずつ、合計2回押すCrate HPが5→0。2回目に「箱が壊れた」と出て箱が消える
消えた後、さらに同じキーを押す新しい死亡メッセージは出ず、参照エラーも出ない

最後の確認では、敵はComponentのHPチェック、箱はActorのIs Validが、それぞれ続きを止めます。画面のメッセージは上下の位置ではなく、Enemy/Crateのラベルで見分けてください。

動かない場合は、F・Gの直後のPrintで入力を確認し、次にTargetActor、追加したComponent、Bindの実行線とEvent接続を確認します。HPの表示は変わるのに姿が消えないなら、OnDied側のBindとHandleDiedを調べます。

次にPlayを止め、BP_HealthComponentの減算へ入れるDamageAmountを、DamageAmount × 0.9 に変えてみます。25ダメージの10%軽減なので、実際に引く量は22.5 です。

再びPlayすると、Fの1回目は77.5、Gの1回目は7.5になります。敵役は5回、箱は2回でHPが0になります。両Actorの計算を書き換えずに、部品1か所の変更が反映されたことを確かめ、確認後は元のDamageAmountへ戻します。

Sponsored

ComponentとOwnerの役割を分ける

今回の体力Componentは、Ownerが敵か箱かを区別していません。HPの計算をして、登録された相手へ変化を知らせています。

方向今回のやり取り
外からComponentへApplyHealthDamageで、減らす量を渡す
Componentから外へOnHealthChanged/OnDiedで知らせる
Owner自身の反応表示する、見えなくする、消す

もしComponentの中へ Get Owner → Cast To BP_Enemy → 敵の死亡処理 と書くと、その処理にはBP_Enemyが必要になります。箱へ取り付けても、同じCastは成功しません。

Castそのものが禁止なのではありません。特定のCharacter専用の移動部品など、使えるOwnerを決めた設計もあります。敵と箱の両方で使う今回の部品では、敵だけの処理を必須にしない ことが大切です。

Componentは計算と通知だけを担当し、表示や消去はOwnerが決める。中でBP_EnemyへCastすると箱で使えなくなる

通知は、ゲーム中の全Actorへ無条件に届く放送ではありません。そのComponentのDispatcherへBindした相手だけが受け取ります。部品ごとに通知先も別なので、敵のHP変更で箱のHandleDiedが呼ばれるわけではありません。

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

弾・HPバー・破片をつなぐには

弾が当たった相手へ、今回のDamageTargetと同じ確認を行えば、体力部品を持つ相手へダメージを渡せます。入力や弾の準備はSpawn ActorとProjectile Movementへ進めます。

標準のApply Damageを使う場合は、ActorのEvent AnyDamageで受けた量を、自作のApplyHealthDamageへ渡す方法があります。Componentを追加するだけで自動接続されるわけではありません(→ 体力とダメージ)。

HPバーはOnHealthChangedで受け取った値から更新し、破片や光はOwnerのHandleDiedへ加えます。UMGNiagaraでそれぞれ作れます。

同じComponentを2個付けたら?

Get Component by Classは、指定したClassに一致する最初の部品を1個返します。今回のBP_HealthComponentは、各Actorに1個だけ追加します。部位ごとに体力を持たせたいなら、どの部品を攻撃するかも区別する必要があります。

毎フレームの処理は、必要になってから

今回の体力計算は、ダメージ関数が呼ばれたときだけ動きます。ComponentのClass DefaultsでStart with Tick Enabledを確認し、不要ならオフにします。Tickの既定値に頼らず、必要な処理があるかで判断します(→ Tickとイベントの使い分け)。

通知を受け取る相手が変わる場合

今回のOwnerは、自分に付いたComponentへBeginPlayでBindします。別のActorの部品を監視するUIなどでは、表示対象を替えたときに古い接続をUnbindしてから、新しい相手へBindします。

「誰の通知を、いつまで受けたいか」を決めると、解除する場所も見えてきます。詳しい接続・解除はEvent Dispatcherで扱います。

自作の前に、標準の部品も探す

回転にはRotating Movement、弾の移動にはProjectile Movementなど、標準Componentもあります。コイン集めゲームでは、回転するコインにRotating Movementを使っています。

まとめ

BP_HealthComponentへ体力の計算をまとめ、敵役と箱へ1個ずつ追加しました。計算の定義は共通でも、HPと通知先は各個体が持ち、力尽きた後の反応はOwnerへ任せています。

似た処理を複数のActorへ書いていたら、何を共通の機能にし、何を本体の仕事に残すか考えてみてください。部品同士の連携を増やすときは、アクター間通信の3つの方法も判断の助けになります。

参考リンク

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