Tag Architecture¶
Gameplay Tags are the connective tissue of GAS. A well-designed tag hierarchy makes your project navigable, your effects composable, and your team productive. A poorly designed one creates confusion, duplicates, and bugs that are hard to trace.
This page covers the principles and gives you a battle-tested starting point.
Design Principles¶
1. Tags Are a Taxonomy, Not a Database¶
Tags describe what something is, not what it does. Damage.Type.Fire describes a damage type. ApplyBurnEffectToTargetAndPlayFireParticles describes an action -- that's not a tag, that's an ability.
2. Shallow Hierarchies with Meaningful Depth¶
Two to four levels deep is the sweet spot. One level is too flat (no grouping). Five or more is too deep (hard to navigate, easy to misplace).
Good: Damage.Type.Fire
Good: CrowdControl.Stun
Fine: Ability.Combat.Melee.LightAttack
Bad: Game.Combat.Player.Ability.Melee.Sword.LightAttack.Version2
3. Leaf Tags for Specifics, Parent Tags for Queries¶
Apply leaf tags to effects and abilities. Use parent tags in requirements and queries.
This works because of GAS's tag hierarchy matching -- a tag query for CrowdControl matches anything under it.
4. Singular Nouns for Categories¶
Damage.Type.Fire, not Damage.Types.Fire. Ability.Combat, not Abilities.Combat. Singular reads better and is consistent.
5. No Verbs in Tag Names¶
Tags are state, not actions. State.Sprinting (yes), Action.Sprint (no). CrowdControl.Stunned or CrowdControl.Stun (both fine -- pick one convention and stick with it).
The 21-Namespace Starter Preset¶
This is a starting point that covers most action/RPG games. Add or remove namespaces based on your game's needs.
| Namespace | Purpose | Example Tags |
|---|---|---|
Ability |
Ability identification and types | Ability.Combat.Melee, Ability.Utility.Heal |
AI |
AI behavior states | AI.State.Alerted, AI.Behavior.Patrol |
Animation |
Animation state flags | Animation.FullBody, Animation.UpperBody |
Combat |
Combat states and phases | Combat.InCombat, Combat.Combo.1 |
Combo |
Combo tracking | Combo.Count.1, Combo.Window.Open |
Cooldown |
Cooldown identification | Cooldown.Ability.Fireball |
CrowdControl |
CC types | CrowdControl.Stun, CrowdControl.Slow |
Damage |
Damage types and properties | Damage.Type.Fire, Damage.Type.Physical |
Enemy |
Enemy classification | Enemy.Type.Boss, Enemy.Type.Minion |
Equipment |
Equipment slots and types | Equipment.Slot.Weapon, Equipment.Type.Sword |
Event |
Gameplay events | Event.Montage.ComboWindow, Event.Death |
GameplayCue |
Cue routing | GameplayCue.Hit.Physical, GameplayCue.Status.Burning |
Immunity |
Immunity flags | Immunity.CrowdControl, Immunity.Damage.Fire |
InputTag |
Input action mapping | InputTag.Attack, InputTag.Dodge |
Movement |
Movement states | Movement.Airborne, Movement.Swimming |
Phase |
Game phase tracking | Phase.Round.1, Phase.Intermission |
Resistance |
Damage resistance types | Resistance.Fire, Resistance.Physical |
SetByCaller |
SetByCaller magnitude keys | SetByCaller.Damage, SetByCaller.Duration |
State |
Character states | State.Sprinting, State.Dead, State.Invulnerable |
Status |
Status effect types | Status.Burning, Status.Poisoned, Status.Bleeding |
Weapon |
Weapon identification | Weapon.Type.Sword, Weapon.Slot.Primary |
This is a starting point
Don't add all 21 on day one if your game doesn't need them. Start with the 5-6 you'll use immediately (Ability, Damage, State, GameplayCue, InputTag, SetByCaller) and add more as needed.
Loading Tags from .ini Files¶
Tags can be defined in DefaultGameplayTags.ini or a custom .ini file. This is the recommended approach for teams because it's version-controllable and diff-friendly.
DefaultGameplayTags.ini¶
[/Script/GameplayTags.GameplayTagsSettings]
+GameplayTagList=(Tag="Ability.Combat.Melee",DevComment="Melee combat abilities")
+GameplayTagList=(Tag="Ability.Combat.Ranged",DevComment="Ranged combat abilities")
+GameplayTagList=(Tag="Damage.Type.Physical",DevComment="Physical damage")
+GameplayTagList=(Tag="Damage.Type.Fire",DevComment="Fire damage")
+GameplayTagList=(Tag="State.Dead",DevComment="Character is dead")
+GameplayTagList=(Tag="CrowdControl.Stun",DevComment="Stunned, cannot act")
Custom Tag .ini Files¶
You can split tags across multiple files using the GameplayTagRedirects and GameplayTagTableList settings:
[/Script/GameplayTags.GameplayTagsSettings]
+GameplayTagTableList=/Game/Data/Tags/CombatTags
+GameplayTagTableList=/Game/Data/Tags/AbilityTags
These reference DataTable assets with tag definitions.
C++ Native Tags¶
For tags that C++ code references frequently, define them as native tags to avoid string lookups:
// In a header
UE_DECLARE_GAMEPLAY_TAG_EXTERN(TAG_State_Dead);
UE_DECLARE_GAMEPLAY_TAG_EXTERN(TAG_CrowdControl_Stun);
// In a cpp file
UE_DEFINE_GAMEPLAY_TAG(TAG_State_Dead, "State.Dead");
UE_DEFINE_GAMEPLAY_TAG(TAG_CrowdControl_Stun, "CrowdControl.Stun");
These are resolved at startup and avoid the overhead of FGameplayTag::RequestGameplayTag() at runtime.
Tag Governance for Teams¶
As your team grows, tag sprawl becomes a real problem. Two people independently creating Damage.Fire and DamageType.Fire is the classic failure mode.
Strategies¶
Single owner. One person (or a small group) owns the tag hierarchy and reviews all additions. Works for teams up to ~10.
Namespace ownership. Different people own different namespaces. The combat designer owns Damage.* and CrowdControl.*. The ability designer owns Ability.*. Works for larger teams.
PR-based governance. Tags are defined in .ini files, and changes go through code review like any other code change. The diff is clear and reviewable.
Documentation table. Maintain a living document (or use the DevComment field in the .ini) that explains each tag's purpose. Review it periodically and prune unused tags.
Tag Redirects¶
When you need to rename a tag (it happens), use redirects instead of find-and-replace:
[/Script/GameplayTags.GameplayTagsSettings]
+GameplayTagRedirects=(OldTag="DamageType.Fire",NewTag="Damage.Type.Fire")
This ensures existing assets continue to work while you migrate.
Rules of Thumb¶
- No tag without a consumer. If nothing checks for it, don't create it.
- No duplicate semantics. If
State.Deadexists, don't also createStatus.Dead. - Prefer specific over generic.
CrowdControl.StunoverCC.1. - DevComment everything. Future you (and your teammates) will thank you.
Related Pages¶
- Gameplay Tags -- how tags work in GAS
- Tags and Requirements -- tag-based GE requirements
- Naming Conventions -- broader naming patterns
- Buff/Debuff System -- tags for buff categories