スライムのHPを50から70へ変えたい。倒れた後、すぐ消えるのではなく少し残したい。一方で、HPがマイナスになる不具合は、すべての敵でまとめて直したい。
同じ敵の機能でも、変えたいものは別々です。全員に共通するHPの計算と、種類ごとに調整する数値・演出を分ける と、どこを直せばよいかが見えやすくなります。
この記事では、C++の親クラスにHP管理を置き、子Blueprintで最大HPと倒れ方を変えます。C++クラスを追加してビルドできる人を想定しています。初回の環境構築とマクロの読み方は、C++への第一歩から始めてください。
この記事でわかること
- 共通の処理と、種類ごとの設定を分けて考える
- C++から子Blueprintの演出イベントを呼ぶ
- 20ダメージを送り、HPが50→30→10→0と減ることを確かめる
- C++を変えずに、敵の体力と消えるまでの時間を調整する
基本形:同じ親から、違う敵を作る
親クラス は共通の処理や変数を持つ設計図です。子クラス は、その作りを引き継いで使います。今回はC++のEnemyBaseを親にし、BP_SlimeとBP_Golemという子Blueprintを作ります。

| 置く場所 | 今回の担当 |
|---|---|
| C++の親 | ダメージでHPを減らす。0未満にしない。死亡済みなら二度目の処理をしない |
| 子Blueprint | 最大HPと見た目を選ぶ。被弾を表示し、倒れた後の動きを組む |
HPの計算式を直すときは、親のC++を一か所変えます。スライムだけを強くするときは、BP_Slimeの最大HPを変えます。共通の修正 は親へ、種類ごとの調整は子へ という届き方になります。
これはC++にしかできない共通化ではありません。Blueprintの親やActor Componentでも、同じ処理を使い回せます。ここでは、C++で用意した土台をBlueprintから調整する形を試します。
判断するのは「何を変えたいか」
「頻繁に変わるものはBlueprintへ」は、出発点として役立ちます。ただし、変更頻度だけで全部は決まりません。まず、値を変えたいのか、処理のルールを変えたいのか を分けてみます。

「スライムの最大HPを70にする」は設定の変更です。「どの敵もHPが0を下回らないようにする」はルールの変更です。どちらも同じHPの話ですが、毎回触る場所を分けられます。
宣言する場所と、値を調整する場所は別
C++に変数を宣言しても、その値までコードに固定する必要はありません。
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Enemy|Status")
float MaxHealth = 100.0f;
これは「C++にMaxHealthという変数を用意し、子BlueprintのClass Defaultsで初期値を変えられる」指定です。BP_Slimeで50に設定すれば、その子から作る敵は50で始まります。数値の調整だけなら、C++のビルドを挟まずに試せます。
処理をどちらに書くか迷ったら、次も考えます。
- 誰が調整するか。エディタ上で見ながら試したい処理なら、Blueprintが扱いやすい。
- 必要な機能がノードから使えるか。公開されていないAPIや外部ライブラリを使うなら、C++が候補になる。
- 何に時間がかかっているか。性能が理由なら、処理時間を測ってから対象を選ぶ。
たとえば大量の計算が重いなら、その計算だけをC++へ移す方法があります。敵の見た目やUIまで、まとめて移す必要はありません。
置き場所に迷ったときの目安
| 作りたいもの | 最初の置き場所の例 | 判断するポイント |
|---|---|---|
| 最大HP、移動速度、使うメッシュ | 子Blueprint、Data Asset | コードを開かずに調整したいか |
| 被弾・死亡時の音や見た目 | Blueprint | 見ながら差し替えるか |
| HP計算などの共通ルール | 共通の親やComponent | BPで十分か、C++で管理する利点があるか |
| C++とBPの両方から使うStruct・Enum | C++で型を定義 | 同じ型を両方で扱う必要があるか |
| 試作中の敵AIやレベルの仕掛け | Blueprint | まず挙動を試し、共通部分が見えてから分ける |
| 計測して重いと分かったループ | C++への移行を検討 | そもそも毎回その処理をする必要があるか |
StructやEnumは、Blueprintだけで使うならBlueprintで作って構いません。「型」は、アイテムがどんな項目を持つか、敵がどんな状態を取れるか、といったデータの形です。C++でも同じ形を 使う予定なら、C++で定義してBlueprintへ公開すると扱いやすくなります。
数値の置き場所も、敵が何種類になったら必ず移す、という決まりはありません。見た目や数値の組をまとめて差し替えたくなったら、Data Assetを検討します。

C++へ移すだけでは解決しないこと
Blueprintも検索と差分確認ができる
Blueprintには、使われている場所を探すFind Referencesや、変更前後を比べるUE Diff Toolがあります。「昨日の処理とどこが違うか」を確認できます。
ただし、Blueprintの.uassetはバイナリ形式なので、通常のコードと同じようにGitで行単位の差分を読み、自動でマージする運用には向きません。差分を見ることと、二人の変更を一つにまとめることは別 です。同じBPを同時に触るなら、編集担当を分けるなどの共同作業の決め方が必要になります。
アセットを読み込む量は、参照の持ち方でも変わる
ハード参照 は、あ るアセットが別のアセットを直接必要とするつながりです。元を読み込むと、参照先も一緒に読み込まれます。
たとえばUIがHPを知るためだけに、大きな見た目のアセットを持つBP_Bossの型へ依存していたら、UIを使うだけでもその依存が影響します。HPを読む入口を軽い親に置き、UIはその親の型を使う形を考えられます。

図の矢印は、アセットや型の依存です。右側でも、実際に登場させたボスの見た目は読み込みます。「UIが必要とする型のために、ボスの見た目まで要求する」つながりを減らす考え方です。
C++でも、親クラスがメッシュなどをハード参照すれば読み込みは増えます。Interfaceを入れただけで、他に残った参照が消えるわけでもありません。Reference Viewerで実際のつながりを確かめ、必要なときだけ読む設計はソフト参照と非同期ロードで扱います。
C++のStructも、変更後のデータ確認は必要
既存の型や項目名を変えると、その型を使うアセットやセーブの引き継ぎが必要になることがあります。C++なら変更をテキストで追いやすくなりますが、古い値を自動で守ってくれるわけではありません。大きな変更はコピーで試し、以前のデータを読み戻せるかも確かめます。