GameplayTags used well beyond GAS — Blueprint interfaces, save systems, data tables, AI blackboards — and the decision framework for picking between a tag, an enum, a delegate, an interface, and a subclass.
Chapter 15 introduced Gameplay Tags inside GAS. That's their most visible home, but the tag system is general-purpose — it shows up in Blueprint interfaces, save systems, data tables, and AI blackboards just as often.
State.Stunned, State.Dead — instead of bool sprawl, queryable via HasMatchingGameplayTag().DefaultGameplayTags.ini rather than scattering literal-string RequestGameplayTag() calls.FNativeGameplayTag / UE_DEFINE_GAMEPLAY_TAG in C++ for tags referenced programmatically — it fails fast instead of silently no-op-ing on a typo.State.Debuff.Stunned). Hierarchy matching — HasTag("State.Debuff") matching State.Debuff.Stunned — is lost in a flat namespace.Stacks.3). Tags are presence/absence flags — use Gameplay Effect stacking or SetByCaller for magnitudes.FGameplayTagContainer plus HasAllExactTags / HasAnyTags / MatchesQuery (FGameplayTagQuery) instead of manual loops.The core question before adding a tag: is this a closed set you control, or an open set others — designers, future-you, other systems — will extend?
| Need | Reach for | Why |
|---|---|---|
| Binary state on an actor, queried across systems | GameplayTag on the ASC | Extensible, auto-managed by Gameplay Effect duration |
| Fixed internal mode (small N) | enum | Compile-time safety, no string overhead |
| Notify others when X happens | Delegate | Direct, typed payload, no polling (Chapter 13) |
| Unrelated actor types share a capability | Interface | A contract without inheritance coupling (Chapter 19) |
| Shared replicated fact all clients need | Component or property on GameState | Replication is the point (Chapter 5) |
| Cross-system categorization/filtering (abilities, cues, damage types) | GameplayTag | Hierarchical AND/OR querying across decoupled systems |
Push logic into data, identity into tags, and keep the C++ generic. Avoid a subclass explosion — UGA_FireballWeak, UGA_FireballStrong, and so on — in favor of fewer, generic ability and effect classes differentiated by tags, SetByCaller magnitudes, and data tables.
UGameplayAbility subclass would differ from an existing one only by a number or a tag, parameterize instead of subclassing.
Answer each out loud before re-reading the chapter.