概要
動作確認環境: UE 5.4+
「敵の種類や状態をBoolやEnumで管理しているが、条件分岐が増えすぎて破綻しかけている…」――プロジェクトが大きくなるにつれ、bIsStunned、bIsSwimming、bIsFlying のようなフラグが際限なく増えていく経験は多くの開発者に共通する悩みです。
UEの Gameplay Tags は、こうした状態管理を階層的なタグ構造に置き換えることで、柔軟かつ拡張性の高いゲームシステムを構築するための仕組みです。タグの追加・削除だけでゲームロジックを拡張でき、既存コードの修正が最小限で済むのが大きな利点です。
Gameplay Tagsとは
Gameplay Tagsは、.(ドット)区切りで階層構造を持つ文字列ラベルです。ゲーム内のオブジェクトに概念的なタグ付けを行い、そのタグに基づいてロジックを駆動します。
たとえば、以下のような概念をタグで表現できます。
- オブジェクトの属性:
Character.Enemy.Zombie— キャラクターが敵であり、ゾンビであることを示す - 状態や能力:
Movement.Mode.Swimming— キャラクターが泳いでいる状態 - イベント:
GameplayEvent.RequestReset— ゲームリセットの要求
Event.Movement.Dash というタグは3つの階層を持ちます。これにより、Event.Movement に属する全タグをまとめてチェックする部分マッチングが可能です。新しい移動方法を追加したいときは、Event.Movement.Teleport のようにタグを1つ追加するだけで、既存の Event.Movement を監視しているロジックが自動的にそのタグも認識します。Enumのように定義を変更して回る必要がありません。
タグの定義方法
Gameplay Tagsをプロジェクトで使うには、まずタグ辞書にタグを登録する必要があります。定義方法は3つあり、プロジェクトの規模やワークフローに応じて使い分けます。
1. プロジェクト設定で直接追加
最もシンプルな方法です。小規模プロジェクトやプロトタイプに適しています。
- プロジェクト設定 > GameplayTags > Import Tags From Config を有効化
- Manage Gameplay Tags ボタンで Gameplay Tag Manager を開く
- Add (+) をクリックし、Name・Comment・Sourceを入力して追加
タグは右クリックで名前変更・削除・サブタグ追加が可能です。大規模プロジェクトでは Config/Tags ディレクトリに機能別の .ini ファイルを分けると、チーム間での競合を避けやすくなります。
2. データテーブルからインポート
行タイプ GameplayTagTableRow のデータテーブルを作成し、プロジェクト設定の Gameplay Tag Table List に登録します。.csv / .json からのインポートにも対応しているため、外部ツールやスプレッドシートでタグを管理したい場合に便利です。エディタ実行中でもデータテーブルの変更が反映される点も利点です。
3. C++で定義する(ネイティブタグ)
C++でタグを定義すると、コンパイル時にタグの存在が保証され、タイポによるバグを防げます。NativeGameplayTags.h で提供されるマクロを使用します。
// MyTags.h
#pragma once
#include "NativeGameplayTags.h"
UE_DECLARE_GAMEPLAY_TAG_EXTERN(TAG_Movement_Walking);
UE_DECLARE_GAMEPLAY_TAG_EXTERN(TAG_Movement_Swimming);
// MyTags.cpp
#include "MyTags.h"
UE_DEFINE_GAMEPLAY_TAG_COMMENT(TAG_Movement_Walking,
"Movement.Mode.Walking", "Default character movement");
UE_DEFINE_GAMEPLAY_TAG_COMMENT(TAG_Movement_Swimming,
"Movement.Mode.Swimming", "Character is swimming");
必須:
Build.csのPublicDependencyModuleNamesに"GameplayTags"モジュールを追加してください。追加しないとリンカーエラーが発生します。
利用可能なマクロの一覧です。
| マクロ | 用途 |
|---|---|
UE_DECLARE_GAMEPLAY_TAG_EXTERN | .hファイルでタグを外部宣言 |
UE_DEFINE_GAMEPLAY_TAG | .cppファイルでコメントなし定義 |
UE_DEFINE_GAMEPLAY_TAG_COMMENT | .cppファイルでツールチップコメント付き定義 |
UE_DEFINE_GAMEPLAY_TAG_STATIC | ファイルローカルなタグを定義(DECLAREとペアにする必要なし) |
大規模プロジェクトでの実装例は Lyra Sample Game の LyraGameplayTags.h / .cpp が参考になります。タグをカテゴリ別にヘッダーファイルに整理するパターンが確認できます。
ランタイムでのタグ取得
ネイティブタグを定義せず、文字列からタグを動的に取得することも可能です。
FGameplayTag Tag = FGameplayTag::RequestGameplayTag(FName("Movement.Mode.Walking"));
データテーブルやコンフィグからタグ名を読み込むケースで便利ですが、文字列のタイポに対してコンパイル時のチェックが効かないため、頻繁にアクセスするタグはネイティブ定義を推奨します。
Tag ContainerとTag Query
Tag Container(FGameplayTagContainer)
ゲーム内のオブジェクトは通常、複数のタグを同時に持ちます。たとえばあるキャラクターが「敵」であり「ゾンビ」であり「毒状態」であるような場合です。FGameplayTagContainer は、こうした複数タグをまとめて管理するためのコンテナです。
// タグコンテナの基本操作
FGameplayTagContainer TagContainer;
// タグの追加・削除
TagContainer.AddTag(TAG_Movement_Walking);
TagContainer.RemoveTag(TAG_Movement_Walking);
// 条件チェック
bool bHas = TagContainer.HasTag(TAG_Movement_Walking); // 特定タグを持つか
bool bAny = TagContainer.HasAny(OtherContainer); // いずれかを持つか
bool bAll = TagContainer.HasAll(OtherContainer); // すべて持つか
HasTag は階層の親タグでもマッチします。たとえば Movement.Mode.Walking を持つコンテナに対して Movement.Mode で HasTag を呼ぶと true が返ります。これが部分マッチングの仕組みです。完全一致のみを判定したい場合は HasTagExact を使います。
| メソッド | 判定方法 |
|---|---|
HasTag | 階層マッチ(親タグでもtrue) |
HasTagExact | 完全一致のみ |
注意: 空の
FGameplayTagContainerを引数として条件関数に渡すと、HasAll以外はfalseを返します。HasAllは「欠落タグなし」と判定されるためtrueになります。この挙動はロジックのエッジケースで注意が必要です。
Tag Query(FGameplayTagQuery)
より複雑な条件判定が必要な場合は、FGameplayTagQuery を使います。複数の条件を1つの変数にまとめて表現できるため、Blueprintでノードを大量に繋ぐ必要がなくなります。
| 表現 | 意味 |
|---|---|
| Any Tags Match | クエリのタグが1つでもコンテナにある |
| All Tags Match | クエリのタグが全てコンテナにある |
| No Tags Match | クエリのタグがコンテナに1つもない |
さらにサブ表現の組み合わせ(Any/All/No Expressions Match)もサポートしています。たとえば「Movement.Swimming を持ち、かつ Status.Stunned を持たない」のような複合条件を、Blueprintの1ノードやC++の1変数で表現できます。
C++でのタグ定義 とアクセス効率化
IGameplayTagAssetInterface
C++でGameplay Tagsを多用する場合、毎回オブジェクトをキャストしてタグコンテナにアクセスするのは煩雑です。IGameplayTagAssetInterface を実装すると、キャストなしでオブジェクトのタグを取得できるようになります。
// TaggedActor.h
UCLASS()
class AMyTaggedActor : public AActor, public IGameplayTagAssetInterface
{
GENERATED_BODY()
public:
virtual void GetOwnedGameplayTags(
FGameplayTagContainer& TagContainer) const override
{
TagContainer = OwnedTags;
}
protected:
UPROPERTY(EditAnywhere, Category = "Tags")
FGameplayTagContainer OwnedTags;
};
このインターフェースを実装したアクターは、型を問わず IGameplayTagAssetInterface として扱えます。複数のコンテナからタグを集約したり、Blueprintで宣言されたタグにアクセスしたりといったカスタマイズも GetOwnedGameplayTags のオーバーライド内で実現できます。
Lyra Sample Game の ALyraTaggedActor クラスが実践的な実装例です。
タグ編集の制限設定
チーム開発では、コアシステムに使われる重要なタグが意図せず変更されるリスクがあります。UEではタグの編集権限を制限する仕組みが用意されています。
プロジェクト設定 > Advanced Gameplay Tags > Restricted Config Files で、制限対象の .ini ファイルと編集権限を持つ Owners のリストを指定します。リストされたオーナー以外のユーザーがこれらのタグを編集しようとすると、警告メッセージが表示され確認を求められます。
注意: 制限タグの削除はエディタ上からはできません。削除が必要な場合は
.iniファイルを直接編集する必要があります。
まとめ
- Gameplay Tags はBool/Enumに代わる階層的タグシステムで、大規模プロジェクトでも拡張しやすい
- 定義方法 はプロジェクト設定・データテーブル・C++マクロの3通り。C++定義ならコンパイル時にタイポを検出可能
- Tag Container で複数タグを管理し、Tag Query で複合条件をシンプルに記述
- IGameplayTagAssetInterface でキャストなしのタグアクセスが可能
- チーム開発では 制限設定 で重要タグを保護
さらに学ぶために
- Gameplay Tags - UE5公式ドキュメント
- Lyra Sample Game — 大規模プロジェクトでのGameplay Tags実装例
- FGameplayTagContainer API — C++ APIリファレンス
- Gameplay Ability System — Gameplay Tagsの最大の活用先であるGASの公式ドキュメント