【Unreal Engine】Gameplay Tag入門:Enumで増え続ける敵の種類を階層タグで整理する

作成: 2026-02-07最終更新: 2026-07-20

Enum管理が破綻する理由と、階層つきタグ Enemy.Undead.Skeleton で解決する方法をBlueprint中心に図解。Project Settingsでの追加、Has Tag / Has Any / Has All の使い分け、敵を増やしても書き換え不要な聖水の実装まで。

敵の種類をEnumで管理していたら、新しい敵を出すたびにEnumを開くことになった。さらに「アンデッドにだけ効く聖水」を作ろうとして、Switch on Enum の分岐がスケルトン・ゾンビ・グールと並び、敵が増えるたびに聖水のBlueprintも直しに行く。

小さな試作ならそれでも動きます。ただ、種類が増えるほど「敵を1体足す作業」が「あちこちを直す作業」に変わっていきます。これを解きほぐす道具が Gameplay Tag です。この記事では、Enemy.Undead.Skeleton のような階層つきの名札で敵を分類し、種類が増えても判定側を書き換えずに済む形を、Blueprint中心に解説します。

階層になったタグのラベルが並び、その一部にまとめて印がついている図

この記事でわかること

  • Gameplay Tag = . で階層をつけた名札
  • Enum・Nameとの決定的な違いは 親タグでの一括判定
  • Project Settingsでの追加と、DefaultGameplayTags.ini での管理
  • Has Tag / Has Any Tags / Has All Tags / Matches Tag の使い分け
  • 実践:敵を増やしても書き換え不要な アンデッド特効の聖水

Sponsored

Enumが破綻するところ

Enumは「候補が決まっている値」を扱うのに向いた仕組みです。敵が3種類しかいないうちは、これで何の問題もありません。

問題が出るのは 分類が増えたときと、まとめて扱いたくなったとき です。

左:Enumのリストから各処理へ線が集中して絡んでいる図。右:階層タグの親ノード1つから処理へ1本だけ線が伸びている図

E_EnemyTypeSkeleton を足すと、Switch on Enum を使っている全Blueprintに新しいピンが生えます。聖水も、聖属性の魔法も、ネクロマンサーの蘇生も、全部開いて繋ぎ直しです。 敵を1体足すたびに、敵と無関係なアセットを触ることになります。

さらにEnumは平坦です。「アンデッド全般」という中間のまとまりを表現できないので、「スケルトンまたはゾンビまたはグールなら」と列挙し続けるしかありません。

Name(文字列)で管理すれば追加は自由ですが、今度はタイポが実行時まで気づけません。"Undead""undead" のどちらで書いたか覚えていられなくなります。

Gameplay Tagは、この2つの弱点をどちらも埋めます。 追加が自由で、タグは辞書から選ぶので綴りを間違えず、しかも階層でまとめて扱えます。

Gameplay Tagは階層つきの名札

Gameplay Tagは、.(ドット)で区切った階層を持つラベルです。

Enemyを頂点に、UndeadとBeastが枝分かれし、Undeadの下にSkeleton・Zombie・Ghoulがぶら下がる樹形図。Undeadの枝全体が囲われている
Enemy
├─ Enemy.Undead
│   ├─ Enemy.Undead.Skeleton
│   ├─ Enemy.Undead.Zombie
│   └─ Enemy.Undead.Ghoul
└─ Enemy.Beast
    ├─ Enemy.Beast.Wolf
    └─ Enemy.Beast.Bear

決定的なのは 子タグは親タグにも一致する という性質です。Enemy.Undead.Skeleton を持つ敵に対して Enemy.Undead で判定すると true が返ります。Enemy で判定しても true です。

この一方通行が効きます。「アンデッドに効く」処理は Enemy.Undead を見るだけでよく、後から Enemy.Undead.Wraith を追加しても、 処理側は一文字も変わりません

逆向きは成立しません。Enemy.Undead しか持たない敵に Enemy.Undead.Skeleton で判定すると false です。 親で問えば広く当たり、子で問えば狭く当たる と覚えてください。

タグは敵の種類だけでなく、状態や能力にも使えます。

使いどころタグの例
種族・分類Enemy.Undead.Skeleton
状態Status.Debuff.Poison / Status.Stunned
属性・耐性Damage.Type.Holy / Immune.Fire
装備の分類Item.Weapon.Sword.TwoHanded

Gameplay TagはGameplay Ability System(GAS)でも中核として使われていますが、 GASを導入しなくても単体で使えます 。この記事はGASを前提にしません。GAS自体を入れるべきか迷ったら Gameplay Ability System入門 が判断の助けになります。

Sponsored

タグを追加する2つの方法

タグは使う前に 辞書へ登録 します。登録していないタグは、Blueprintのプルダウンに出てきません。

左にProject SettingsのGameplay Tags画面のツリーと+ボタン、右にDefaultGameplayTags.iniのテキスト行を並べた図。両者が同じものを指す矢印

方法1:Project Settingsから追加する

普段はこちらです。

  1. EditProject SettingsProject カテゴリの GameplayTags を開く
  2. Gameplay Tags+(Add New Gameplay Tag) をクリック
  3. NameEnemy.Undead.Skeletonフルパスで 入力する
  4. Comment に用途を書き、Add New Tag で確定

EnemyEnemy.Undead を先に作る必要はありません。 フルパスを入力すれば中間の階層は自動で作られます

登録済みのタグは右クリックから名前変更・削除・子タグの追加ができます。 名前変更(Rename)は参照を追従してくれるので、直接iniを書き換えるより安全です。

方法2:iniファイルで管理する

追加したタグは、既定でプロジェクトの Config/DefaultGameplayTags.ini に保存されます。

[/Script/GameplayTags.GameplayTagsSettings]
+GameplayTagList=(Tag="Enemy.Undead.Skeleton",DevComment="骨の敵")
+GameplayTagList=(Tag="Enemy.Undead.Zombie",DevComment="腐った敵")
+GameplayTagList=(Tag="Enemy.Beast.Wolf",DevComment="獣の敵")

テキストなのでバージョン管理の差分が読めるのが利点です。エディタを閉じた状態で直接編集することもできます。

規模が大きくなったら、Project Settingsのタグ追加時に Source を切り替えて 機能ごとに別のiniへ分ける と、チームで同じ行を編集する競合を減らせます。

C++で定義する選択肢もあります。 NativeGameplayTags.hUE_DECLARE_GAMEPLAY_TAG_EXTERN / UE_DEFINE_GAMEPLAY_TAG_COMMENT を使うと、C++コードからタグを変数として参照でき、綴りの誤りがコンパイル時に見つかります。使う場合は Build.csPublicDependencyModuleNames"GameplayTags" の追加が必要です(→ BlueprintからC++への第一歩)。

判定ノードの使い分け

Blueprintで扱う型は2つです。

中身使いどころ
Gameplay Tagタグ 1つ「このダメージの属性」など、1つに決まるもの
Gameplay Tag Containerタグの 集合「この敵が持つ性質」など、複数持つもの
4つの判定ノードを縦に並べ、それぞれ左に入力タグの集合、右にtrue/falseの結果を示した比較図

判定ノードは、対象がコンテナか単体かで名前が変わります。

ノード対象判定内容
Has Tagコンテナ指定タグ またはその子 を持つか
Has Any Tagsコンテナ指定した複数タグの どれか1つでも 持つか
Has All Tagsコンテナ指定した複数タグを すべて 持つか
Matches Tag単体タグそのタグが指定タグ またはその子

具体例で見ます。敵が Enemy.Undead.SkeletonStatus.Debuff.Poison の2つを持っている場合です。

問い合わせ結果
Has Tag(Enemy.Undead)true(子タグなので一致)
Has Tag(Enemy.Beast)false
Has Any Tags(Enemy.Undead, Enemy.Beast)true(片方だけ一致すればよい)
Has All Tags(Enemy.Undead, Status.Debuff)true(両方一致)
Has All Tags(Enemy.Undead, Immune.Fire)false

「〜に効く」は Has Tag 、「〜か〜に効く」は Has Any Tags 、「〜かつ〜のときだけ」は Has All Tags です。

完全一致で判定したいときは Exact 版を使います。 Has Tag Exact は階層を無視し、Enemy.Undead.Skeleton に対して Enemy.Undead で問うと false を返します。「アンデッド全般ではなく、スケルトンだけ」という限定が必要なときの選択肢です。

空のコンテナには落とし穴があります。 判定に渡すタグの集合が空の場合、Has Any Tagsfalse を返しますが、Has All Tags は「欠けているタグがない」と解釈されて true を返します。条件をデータから流し込む設計にするときは、空のケースを一度確かめてください。

Sponsored

実践:アンデッド特効の聖水を作る

ローグライクの属性特効アイテム、ホラーゲームの浄化アイテム、タワーディフェンスの対空専用タワー。 「特定のグループにだけ強く効く」 という仕組みは、ジャンルを問わず登場します。ここでは、敵の種類を増やしても聖水側を一切触らずに済む形を組み立てます。

プレイヤーが投げた聖水が、スケルトンとゾンビには大きなダメージ数字、オオカミには小さな数字で当たっている場面図

再現用の準備: Third Person テンプレートで新規プロジェクトを作ります。あらかじめProject Settingsで次の4つのタグを登録しておきます。

Enemy.Undead.Skeleton
Enemy.Undead.Zombie
Enemy.Beast.Wolf
Damage.Type.Holy
種類名前型 / 初期値
Blueprint Class(Actor)BP_EnemyBase3体の親クラス
BP_EnemyBase の変数EnemyTagsGameplay Tag Container / 空。 Instance Editable をオン
BP_EnemyBase の変数HealthFloat / 100.0
子BlueprintBP_SkeletonEnemyTags の既定値に Enemy.Undead.Skeleton
子BlueprintBP_ZombieEnemyTags の既定値に Enemy.Undead.Zombie
子BlueprintBP_WolfEnemyTags の既定値に Enemy.Beast.Wolf
Blueprint Class(Actor)BP_HolyWaterSphere Collision(Radius 200.0)を持つ
BP_HolyWater の変数BaseDamageFloat / 20.0
BP_HolyWater の変数HolyMultiplierFloat / 5.0
BP_HolyWater の変数TargetTagGameplay Tag / 既定値 Enemy.UndeadInstance Editable をオン

ステップ1:敵の親クラスを作る。 コンテンツブラウザで右クリック → Blueprint ClassActorBP_EnemyBase と名付けます。

My Blueprintパネルで変数を2つ追加します。EnemyTags は型のプルダウンで Gameplay Tag Container を選びます。HealthFloat にして、詳細パネルの Default Value100.0 を入れます。両方とも Instance Editable にチェックを入れておくと、レベルに置いた個体ごとにタグを足せます。

ステップ2:敵を3体作る。 BP_EnemyBase を右クリック → Create Child Blueprint Class で3つ作ります。それぞれを開き、EnemyTagsDefault Value+ からタグを選びます。 プルダウンには登録済みのタグしか出てこないので、ここで綴りを間違えることはありません。

ステップ3:ダメージ処理を親クラスに書く。 BP_EnemyBaseApplyHolyDamage というカスタムイベントを作り、入力に Damage(Float)を追加します。中身は Health から Damage を引いて設定するだけです。

ステップ4:聖水のBlueprintを組む。 BP_HolyWater を作り、Sphere Collision コンポーネントを追加して Sphere Radius200.0 にします。変数3つを上の表のとおりに用意し、On Component Begin Overlap から次のグラフを組みます。

On Component Begin OverlapからCast、Has Tag、Branch、Multiply、ApplyHolyDamageへ左から右へつながるBlueprintノードグラフ
BP_HolyWater
On Component Begin Overlap (Sphere)
  → Cast To BP_EnemyBase(Object: Other Actor)
      成功 → Get EnemyTags(As BP Enemy Base から)
          → Has Tag(Container: EnemyTags / Tag: TargetTag)
              → Branch
                  True  → Multiply(BaseDamage × HolyMultiplier)→ ApplyHolyDamage(Target: As BP Enemy Base)
                  False → ApplyHolyDamage(Damage: BaseDamage、Target: As BP Enemy Base)

Has Tag ノードは、EnemyTags ピンからドラッグして検索すると出てきます。Tag 入力には変数 TargetTag を繋ぎます。ここを直接タグリテラルで指定してもよいのですが、変数にしておくと レベルに置いた聖水ごとに対象を変えられます (獣特効の聖水は Enemy.Beast に差し替えるだけです)。

ステップ5:レベルに置いて確認する。 BP_Skeleton / BP_Zombie / BP_Wolf を並べて配置し、BP_HolyWater をその中央に置きます。ApplyHolyDamage の中で Print String を使い、残りHPを表示させておくと確認しやすくなります(→ Print Stringで値を確認する)。

Playして聖水の範囲に敵が入ると、次の値が出るはずです。

受けるダメージ残りHealth
BP_Skeleton100.0(20 × 5)0.0
BP_Zombie100.00.0
BP_Wolf20.080.0

オオカミだけが80で残っていれば成功です。3体とも100ダメージなら Has Tag に繋いだタグを、3体とも20なら EnemyTags の設定を疑ってください。

ここからが本題です。 BP_EnemyBase の子として BP_Wraith を作り、Project Settingsで Enemy.Undead.Wraith を追加して EnemyTags に設定します。 BP_HolyWater を開かずに レベルへ置いてPlayすると、レイスは100ダメージを受けて倒れます。これがEnumとの決定的な違いです。

ポイントは2つです。

  • 判定は親タグで書く: Has Tag に渡すのは Enemy.Undead であって Enemy.Undead.Skeleton ではありません。「どこまで広く効かせたいか」の階層でタグを選ぶと、追加に強い形になります
  • タグはデータ、判定はロジック: 敵が持つタグはレベルやBlueprintの既定値(データ)、聖水が見るタグは変数(設定)です。 コードに種類名を埋め込まない ことで、拡張がデータ側の作業だけで済みます。Data Tableと組み合わせれば敵のパラメータごと外に出せます(→ Data Tableでゲームデータを管理する
Sponsored

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

Gameplay Tag Containerは実行中に足し引きできます。 状態管理に使う場合、毒を受けたら Add Gameplay TagStatus.Debuff.Poison を足し、解除で Remove Gameplay Tag します。bIsPoisoned のようなbool変数を増やし続けるより、状態が1つの場所にまとまります。

タグの名前は「上から下へ絞り込む」順に並べます。 Skeleton.Enemy.Undead のように細かいものを先頭に置くと、階層でまとめる利点が消えます。 左が大きい分類、右へ行くほど具体 が原則です。

深くしすぎないことも大切です。 Item.Weapon.Melee.Sword.OneHanded.Iron.Rusty まで作ると、どの階層で判定すべきか自分でも分からなくなります。実際に「まとめて扱いたい単位」がある階層だけを作れば十分です。

タグを増やす前に、本当にタグが要るかを考えてください。 値が2つしかなく、増える見込みもないなら bool で十分です。Gameplay Tagが効くのは 分類が増える見込みがあり、かつ「まとめて扱いたい」ときだけ です。

大規模な例を見たいときはLyraが参考になります。 Epic公式のサンプル Lyra Sample Game は、タグをカテゴリ別のヘッダに整理してC++定義しています。ただし規模が大きいので、個人開発でそのまま真似する必要はありません。


まとめ

EnumName(文字列)Gameplay Tag
追加のしやすさ定義変更で全体に波及自由自由
綴り間違い起きない実行時まで気づけないプルダウン選択なので起きない
まとめて判定列挙するしかないできない親タグで一発
  • Gameplay Tagは . で階層をつけた名札 。BlueprintだけでもC++なしで使える
  • 子タグは親タグに一致する 。この一方通行が「追加しても壊れない」の正体
  • 追加は Project Settings から。実体は Config/DefaultGameplayTags.ini のテキスト
  • コンテナには Has Tag / Has Any Tags / Has All Tags 、単体タグには Matches Tag
  • 判定は 広く効かせたい階層のタグ で書く

タグで種類を整理できたら、次はその種類ごとの数値をデータ側へ出す番です。敵ごとのHPや報酬をまとめて管理する方法は Data Tableでゲームデータを管理する で、種類ごとの振る舞いを差し替える方法は Blueprint Interfaceの記事 で扱っています。

あなたのプロジェクトで、いま Switch on Enum がいちばん長く伸びているのはどのBlueprintでしょうか。