敵にも、壊せる木箱にも、砦のタワーにも体力を持たせたい。3つのBlueprintに同じ体力処理をコピペすれば、とりあえず動きます。ただ、仕様を変えるたびに3箇所とも直すことになります。
この問題を解くのが 自作のBlueprint Component です。機能を「差し込み式の部品(カートリッジ)」として1回だけ作れば、どんなActorにも挿せます。継承関係も要りません。この記事では、Componentの仕組みと設計原則、そして「どのActorにも挿せる体力Component」の組み方を解説します。
この記事でわかること
- Blueprint Component= 機能のカートリッジ 。継承なしで振る舞いを配れる
- ActorComponentとSceneComponent の使い分け(位置を持つか持たないか)
- 実践:敵にも木箱にも挿せる 体力Component を組む
- 再利用性を守る鉄則 「Componentは相手を選ばない」(キャスト禁止とEvent Dispatcher)
Blueprint Componentとは:機能のカートリッジ
StaticMeshComponent が見た目を、MovementComponent が移動をActorに与えるように(→ ActorとComponentの基本)、 Componentは「Actorに機能を差し込む部品」 です。そしてUEでは、この部品を Blueprintで自作 できます。

| Actor | Component | |
|---|---|---|
| 役割 | ワールドに置かれる本体 | Actorに機能を足す部品 |
| 単体での存在 | できる | できない(必ずActorに挿さる) |
| 再利用の形 | 継承(親子関係が必要) | アタッチ(関係のないActor同士でもOK) |
最大の強みは、 継承関係のない全く別種のActorに同じ振る舞いを配れる ことです。敵キャラと木箱は親子関係にできませんが、「体力Component」なら両方に挿せます。コピペゼロ、修正は部品1箇所だけ。
親クラスの選択:ActorComponent vs SceneComponent
自作Componentを作るとき、最初に親クラスを選びます。基準は 位置(Transform)が必要かどうか の1点だけです。

| 親クラス | 特徴 | 使用例 |
|---|---|---|
| ActorComponent | Transformを持たない、純粋なロジックの入れ物 | 体力管理・インベントリ・ステート管理 |
| SceneComponent | Transformを持ち、Actorの階層に配置できる | カメラアーム・エフェクト発生点・当たり判定の位置 |
体力やインベントリのような「データと計算だけ」の機能はActorComponent、「銃口の位置」のように場所そのものが意味を持つ機能はSceneComponent、と覚えてください。
実践:どのActorにも挿せる体力Componentを組む
作ってみるのが一番早いです。題材は 体力システム 。アクションの敵、探索ゲームの壊せる木箱、タワーディフェンスの砦——「ダメージを受けて、尽きたら壊れる」はジャンルを問わない普遍の仕組みです。
ステップ1:Componentを作る
コンテンツブラウザで右クリック → Blueprint Class → 親クラスに ActorComponent を選び、BP_HealthComponent と名付けます(体力はロジックだけなのでActorComponentですね)。
ステップ2:中身を設計する

| 種類 | 名前 | 役割 |
|---|---|---|
| 変数 | MaxHealth(Float・Instance Editable) | 最大体力。個体ごとに変えられるようにする |
| 変数 | CurrentHealth(Float) | 現在の体力 |
| 関数 | ApplyDamage(入力: DamageAmount) | 受け口 :ダメージを受け付ける |
| Event Dispatcher | OnHealthChanged(出力: NewHealth) | 放送口 :体力の変化を知らせる |
| Event Dispatcher | OnDied | 放送口 :力尽きたことを知らせる |
BeginPlay で満タンにしておき、ApplyDamage で減らします。中身はこれで完成です。
Event BeginPlay(BP_HealthComponent 内)
→ Set CurrentHealth(= MaxHealth) ← 生成時に満タンへ
Function: ApplyDamage(入力: DamageAmount / Float)
→ Set CurrentHealth
= Clamp(Value: Subtract(A: CurrentHealth, B: DamageAmount), Min: 0.0, Max: MaxHealth)
→ OnHealthChanged を Call(NewHealth: CurrentHealth) ← 減るたびに放送
→ Branch(Condition: CurrentHealth <= 0.0)
True → OnDied を Call ← 力尽きたときだけ放送
グラフにするとこの形です。SubtractとClampは実行ピンを持たない計算ノードなので、下段からデータ線だ けで合流します。

Clamp を挟んでいるのは、HPがマイナスに突き抜けないようにするためです。UIのHPバーは CurrentHealth ÷ MaxHealth で割合を出すので、マイナスが入るとバーが逆方向へ伸びてしまいます。
ステップ3:挿して、繋いで、Playする
-
敵に挿す:
BP_Enemyを開き、Componentsパネルの「+ Add」からBP_HealthComponentを追加。詳細パネルでMaxHealthを 100 に -
反応を書く: 追加したComponentを選択 → 詳細パネルのEventsから
OnDiedの「+」 をクリックすると、イベントグラフにバインド済みのイベントが生成されますBP_Enemy のイベントグラフ Event On Died(BP_HealthComponent から) → Print String("敵が倒れた") → Destroy Actor(Target: self)「死んだらどうなるか」は挿された側が決める のがポイントです
-
木箱にも挿す: 同じ手順を
BP_Crateにも。こちらはMaxHealthを 30 にして、OnDiedの反応だけ変えますBP_Crate のイベントグラフ Event On Died(BP_HealthComponent から) → Spawn System at Location(破片のNiagaraエフェクト) → Destroy Actor(Target: self) -
攻撃側から呼ぶ: 弾や剣の当たり判定側は、相手が誰かを気にせずこう書きます
On Component Begin Overlap(弾のCollision) → Get Component by Class(Target: Other Actor, Component Class: BP_HealthComponent) → Is Valid ? Valid → ApplyDamage(Target: 取得したComponent, DamageAmount: 25.0) → Destroy Actor(弾を消す)
Cast To BP_Enemyがどこにも出てこないことに注目してください。攻撃側は「体力コンポーネントを持っているか」だけを見ています。

Playして攻撃してみてください。 敵は4発(100÷25)、木箱は2発(30÷25、端数切り上げ) で壊れ、それぞれの死に方をします。なのに体力のロジックは、プロジェクトに1つしか存在しません。試しに ApplyDamage の先頭に「ダメージを10%軽減する」1ノードを足してみて ください。敵も木箱も、 全Actorに一瞬で反映されます 。これがComponent設計の利点です。
ポイントは2つです。
- 受け口(関数)と放送口(Dispatcher)だけを外に出す: 中の変数は直接触らせない。この規律が再利用性を守ります
- 「死んだらどうなるか」は挿された側の自由: Componentは「死んだよ」と放送するだけ。爆発するか、アイテムを落とすかは受け手が決めます。この分担が次節のテーマです
Componentの通信パターン:相手を選ばない設計
Componentを本当に再利用可能にする鉄則は1つです。 アタッチされる相手(Owner)が誰かを知らないこと 。

- Component → Owner:
OnDiedのように Event Dispatcherで放送 します。Owner側がバインドして、自分に合った反応(死亡アニメ・アイテムドロップ)を実装します - Owner → Component: 関数を直接呼んでOKです(
ApplyDamageなど)。部品への命令は自由です - Component → 外部のシステム: 相手の型に依存したくない場合は Blueprint Interface で汎用メッセージを送ります(→ Blueprint Interfaceの記事)
やってはいけないのが、Component内で Get Owner → 特定クラスへのCast です。
悪い例(Component内)
Get Owner → Cast To BP_PlayerCharacter → プレイヤー固有の関数を呼ぶ
この瞬間、あなたのComponentは BP_PlayerCharacter 専用部品に成り下がります。木箱に挿してもCastが失敗して動きません。設計中は「このComponentは、挿された相手が人でも箱でも塔でも動くか?」と問い続けてください。
おまけ:先に知っておくと良いこと
- ComponentにもTickがある: 自作Componentは既定でTickが有効です。毎フレーム処理が不要なら、Class DefaultsのStart with Tick Enabledをオフにしましょう(→ Event Tickをやめる設計)
- 標準Componentも同じ仕組み:
RotatingMovementComponent(挿すだけで回転)やProjectileMovementComponent(挿すだけで弾道移動)など、エンジン製の便利部品が多数あります。自作の前に「もう存在しないか」を検索する癖をつけると得をします - Dispatcherのバインド解除: Ownerより長生きするオブジェクトがバインドしている場合、破棄時にUnbindしないと空参照を呼ぶ事故につながります。基本の「Owner自身がバインドする」形なら寿命が一致するので安全です
まとめ
| 要点 | 内容 |
|---|---|
| Componentの本質 | 機能のカートリッジ。継承なしで、関係のないActor同士に同じ振る舞いを配れる |
| 親クラスの基準 | ロジックだけなら ActorComponent、位置が要るなら SceneComponent |
| 設計の鉄則 | 相手を選ばないこと。受け口(関数)と放送口(Event Dispatcher)だけを外に出し、Castしない |
| 適用例 | 体力・インベントリ・インタラクション判定・特殊移動など、複数Actorで使う機能すべて |
体力の次にComponent化したくなるのは、通知の仕組みそのものかもしれません。Event Dispatcherの本格的な使い方はEvent Dispatcherによるイベント駆動設計へ、アクター間通信の全体像はアクター間通信の3つの方法へ進みましょう。
あなたのプロジェクトで、いま2箇所以上にコピペされている処理はなんですか? それが、次にカートリッジ化する部品の名前です。