【Unreal Engine】Blueprint Componentで機能を再利用する設計パターン

作成: 2025-12-12最終更新: 2026-07-19

自作Blueprint Componentで機能を再利用する設計を図解。ActorComponentとSceneComponentの使い分け、どのActorにも挿せる体力Componentを組む実践、依存しない通信パターンまで。

敵にも、壊せる木箱にも、砦のタワーにも体力を持たせたい。3つのBlueprintに同じ体力処理をコピペすれば、とりあえず動きます。ただ、仕様を変えるたびに3箇所とも直すことになります。

この問題を解くのが 自作のBlueprint Component です。機能を「差し込み式の部品(カートリッジ)」として1回だけ作れば、どんなActorにも挿せます。継承関係も要りません。この記事では、Componentの仕組みと設計原則、そして「どのActorにも挿せる体力Component」の組み方を解説します。

ハート付きカートリッジを異なる形の箱へ差し込む人形。Componentの再利用のイメージ

この記事でわかること

  • Blueprint Component= 機能のカートリッジ 。継承なしで振る舞いを配れる
  • ActorComponentとSceneComponent の使い分け(位置を持つか持たないか)
  • 実践:敵にも木箱にも挿せる 体力Component を組む
  • 再利用性を守る鉄則 「Componentは相手を選ばない」(キャスト禁止とEvent Dispatcher)

Sponsored

Blueprint Componentとは:機能のカートリッジ

StaticMeshComponent が見た目を、MovementComponent が移動をActorに与えるように(→ ActorとComponentの基本)、 Componentは「Actorに機能を差し込む部品」 です。そしてUEでは、この部品を Blueprintで自作 できます。

1つのHealth Componentが敵・木箱・タワーという違うActorに配られる図。継承なしで、機能を配れる
ActorComponent
役割ワールドに置かれる本体Actorに機能を足す部品
単体での存在できるできない(必ずActorに挿さる)
再利用の形継承(親子関係が必要)アタッチ(関係のないActor同士でもOK)

最大の強みは、 継承関係のない全く別種のActorに同じ振る舞いを配れる ことです。敵キャラと木箱は親子関係にできませんが、「体力Component」なら両方に挿せます。コピペゼロ、修正は部品1箇所だけ。

Sponsored

親クラスの選択:ActorComponent vs SceneComponent

自作Componentを作るとき、最初に親クラスを選びます。基準は 位置(Transform)が必要かどうか の1点だけです。

ActorComponentは位置を持たない頭脳、SceneComponentは位置を持つ部品。ロジックだけならActor、場所が要るならScene
親クラス特徴使用例
ActorComponentTransformを持たない、純粋なロジックの入れ物体力管理・インベントリ・ステート管理
SceneComponentTransformを持ち、Actorの階層に配置できるカメラアーム・エフェクト発生点・当たり判定の位置

体力やインベントリのような「データと計算だけ」の機能はActorComponent、「銃口の位置」のように場所そのものが意味を持つ機能はSceneComponent、と覚えてください。

Sponsored

実践:どのActorにも挿せる体力Componentを組む

作ってみるのが一番早いです。題材は 体力システム 。アクションの敵、探索ゲームの壊せる木箱、タワーディフェンスの砦——「ダメージを受けて、尽きたら壊れる」はジャンルを問わない普遍の仕組みです。

ステップ1:Componentを作る

コンテンツブラウザで右クリック → Blueprint Class → 親クラスに ActorComponent を選び、BP_HealthComponent と名付けます(体力はロジックだけなのでActorComponentですね)。

ステップ2:中身を設計する

BP_HealthComponentの構造。MaxHealthとCurrentHealthのデータ、外から呼ばれるApplyDamage、外へ知らせるOnDied。受け口と放送口だけを外に出す
種類名前役割
変数MaxHealth(Float・Instance Editable)最大体力。個体ごとに変えられるようにする
変数CurrentHealth(Float)現在の体力
関数ApplyDamage(入力: DamageAmount)受け口 :ダメージを受け付ける
Event DispatcherOnHealthChanged(出力: NewHealth)放送口 :体力の変化を知らせる
Event DispatcherOnDied放送口 :力尽きたことを知らせる

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は実行ピンを持たない計算ノードなので、下段からデータ線だけで合流します。

ApplyDamage関数のノードグラフ。SubtractとClampを通してCurrentHealthを更新し、OnHealthChangedを放送、0以下ならOnDiedを放送する

Clamp を挟んでいるのは、HPがマイナスに突き抜けないようにするためです。UIのHPバーは CurrentHealth ÷ MaxHealth で割合を出すので、マイナスが入るとバーが逆方向へ伸びてしまいます。

ステップ3:挿して、繋いで、Playする

  1. 敵に挿す: BP_Enemy を開き、Componentsパネルの「+ Add」から BP_HealthComponent を追加。詳細パネルで MaxHealth100

  2. 反応を書く: 追加したComponentを選択 → 詳細パネルのEventsから OnDied の「+」 をクリックすると、イベントグラフにバインド済みのイベントが生成されます

    BP_Enemy のイベントグラフ
    Event On Died(BP_HealthComponent から)
      → Print String("敵が倒れた")
      → Destroy Actor(Target: self)
    

    「死んだらどうなるか」は挿された側が決める のがポイントです

  3. 木箱にも挿す: 同じ手順を BP_Crate にも。こちらは MaxHealth30 にして、OnDied の反応だけ変えます

    BP_Crate のイベントグラフ
    Event On Died(BP_HealthComponent から)
      → Spawn System at Location(破片のNiagaraエフェクト)
      → Destroy Actor(Target: self)
    
  4. 攻撃側から呼ぶ: 弾や剣の当たり判定側は、相手が誰かを気にせずこう書きます

    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(弾を消す)
    
    弾のOverlapからGet Component by Classで体力コンポーネントを取り、Is Validを通してApplyDamageを呼ぶノードグラフ

    Cast To BP_Enemy がどこにも出てこないことに注目してください。攻撃側は「体力コンポーネントを持っているか」だけを見ています。

敵・木箱・タワーが全員HPバーを持ち、弾が当たった木箱だけHPが減っている。挿した相手は、みんな壊れるようになる

Playして攻撃してみてください。 敵は4発(100÷25)、木箱は2発(30÷25、端数切り上げ) で壊れ、それぞれの死に方をします。なのに体力のロジックは、プロジェクトに1つしか存在しません。試しに ApplyDamage の先頭に「ダメージを10%軽減する」1ノードを足してみてください。敵も木箱も、 全Actorに一瞬で反映されます 。これがComponent設計の利点です。

ポイントは2つです。

  • 受け口(関数)と放送口(Dispatcher)だけを外に出す: 中の変数は直接触らせない。この規律が再利用性を守ります
  • 「死んだらどうなるか」は挿された側の自由: Componentは「死んだよ」と放送するだけ。爆発するか、アイテムを落とすかは受け手が決めます。この分担が次節のテーマです
Sponsored

Componentの通信パターン:相手を選ばない設計

Componentを本当に再利用可能にする鉄則は1つです。 アタッチされる相手(Owner)が誰かを知らないこと

Get OwnerからのキャストはComponentを特定Actorに固定する。Event Dispatcherの放送なら誰でも受け取れる。Componentは相手を選ばない
  • 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箇所以上にコピペされている処理はなんですか? それが、次にカートリッジ化する部品の名前です。