Unreal's framework for data-driven, designer-extensible ability and combat systems — and the architecture behind server-authoritative gameplay.
The Gameplay Ability System is Unreal's plugin for building abilities, attributes, and status effects in a way that is data-driven, networked, and designer-extensible. It was built by Epic for Fortnite and is now used across most major Unreal titles.
GAS solves the hardest problems in ability system design in one framework:
GAS has five building blocks. Every other concept in GAS connects back to these.
The hub of GAS. Every actor that participates in the ability system must have an ASC. It tracks which abilities the actor has, which effects are active, and what its current attribute values are.
Defines a single ability — what it does, what it costs, what cancels it, and how it interacts with the tag system. Subclass this in C++ to define behavior, then create Blueprint subclasses for per-ability configuration.
// C++ defines the ability's execution logic
UCLASS()
class UGA_MeleeAttack : public UGameplayAbility
{
GENERATED_BODY()
public:
virtual void ActivateAbility(...) override;
// Designer sets this in Blueprint subclass
UPROPERTY(EditDefaultsOnly)
float DamageAmount = 25.f;
};
Defines the numeric attributes an actor has — Health, MaxHealth, Mana, AttackPower, etc. Attributes are FGameplayAttributeData structs, not plain floats. The ASC manages them and replicates changes automatically.
UCLASS()
class UPlayerAttributeSet : public UAttributeSet
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintReadOnly, ReplicatedUsing=OnRep_Health)
FGameplayAttributeData Health;
ATTRIBUTE_ACCESSORS(UPlayerAttributeSet, Health)
UPROPERTY(BlueprintReadOnly, ReplicatedUsing=OnRep_MaxHealth)
FGameplayAttributeData MaxHealth;
ATTRIBUTE_ACCESSORS(UPlayerAttributeSet, MaxHealth)
};
The mechanism for changing attributes. A GameplayEffect is a data asset — no code, just configuration. Designers create GameplayEffect assets to define damage, healing, buffs, and debuffs without writing C++. See Section 4 for full detail.
Hierarchical string labels (e.g. Ability.Attack.Melee, Status.Stunned) that connect all of GAS together. Tags control what abilities block each other, what effects get applied, and what cues fire. See Section 3.
Actor
└── UAbilitySystemComponent
├── Granted Abilities (list of UGameplayAbility classes)
├── Active Effects (applied UGameplayEffect instances)
├── Attribute Sets (UAttributeSet subclasses)
└── Tag Container (active FGameplayTags)
GameplayTags are hierarchical labels defined in Project Settings. They are the connective tissue of GAS — nearly every rule in the system is expressed as a tag relationship rather than hardcoded logic.
Ability.Attack.Melee
Ability.Attack.Ranged
Ability.Dodge
Status.Stunned
Status.Silenced
Effect.Damage.Fire
Effect.Buff.Speed
Each UGameplayAbility has tag containers that define its relationship with the tag system:
| Property | Meaning |
|---|---|
| AbilityTags | Tags this ability owns while active (e.g. Ability.Attack.Melee) |
| CancelAbilitiesWithTag | Cancels any active ability that has these tags |
| BlockAbilitiesWithTag | Prevents abilities with these tags from activating while this is active |
| ActivationRequiredTags | Actor must have these tags on its ASC for this ability to activate |
| ActivationBlockedTags | Ability cannot activate if actor has any of these tags |
Status.Stunned to the target's ASC, and any ability with Status.Stunned in its ActivationBlockedTags will automatically be prevented — no hardcoded "if stunned, return" checks anywhere.
Tags are defined in a Project Settings config file — designers can add new tags without touching C++. A designer creating a new ability just picks which tags it owns, blocks, and requires, without needing to understand the underlying implementation.
A UGameplayEffect is a Blueprint asset (no C++ required) that defines a change to an actor's attributes or tags. This is the primary designer-facing layer of GAS.
| Policy | Behavior | Example |
|---|---|---|
| Instant | Applies once and is done | Damage, instant heal |
| Duration | Active for a set time, then removed | Speed boost for 5s |
| Infinite | Active until explicitly removed | Passive armor buff |
Each GameplayEffect contains a list of Modifiers — each one targets an attribute and defines how to change it:
| Operation | Result |
|---|---|
| Add | Attribute += Value |
| Multiply | Attribute *= Value |
| Divide | Attribute /= Value |
| Override | Attribute = Value |
Duration and Infinite effects can define a stacking policy — whether multiple applications stack additively, replace the existing effect, or cap at a maximum stack count. All configured in the asset, no code.
GameplayEffects can also grant and remove tags from the target's ASC. A GE_Stun effect applies Status.Stunned for its duration — when the effect expires, the tag is automatically removed.
Before an actor can activate an ability, it must be granted to its ASC. Abilities are granted as FGameplayAbilitySpec entries:
// Grant an ability at level 1
FGameplayAbilitySpec Spec(
UGA_MeleeAttack::StaticClass(),
1 // level
);
AbilitySystemComponent->GiveAbility(Spec);
In practice, abilities are usually granted from a data asset list in C++ at BeginPlay, or through a GameplayEffect that grants abilities automatically.
| Method | When to use |
|---|---|
| TryActivateAbilityByClass | Activate a specific ability class |
| TryActivateAbilitiesByTag | Activate any ability matching a tag |
| TryActivateAbilityByInputID | Input-bound activation (legacy pattern) |
TryActivate()
→ CanActivateAbility() checks tags, cooldowns, costs
→ ActivateAbility() your gameplay logic runs
→ CommitAbility() deducts costs, starts cooldown
→ EndAbility() cleanup, release resources
Both are GameplayEffects assigned to the ability:
CanActivateAbility returns false.Cooldown.Ability.Melee). While the tag is active, the ability's ActivationBlockedTags prevent re-activation.GameplayCues are the cosmetic layer of GAS — particle effects, sounds, and camera shakes that respond to gameplay events without coupling the logic layer to presentation.
A GameplayCue is triggered by a tag (e.g. GameplayCue.HitImpact.Fire) and the system routes it to a UGameplayCueNotify Blueprint asset that handles the visual/audio response.
GameplayCue.HitImpact.FireGAS is built for server-authoritative multiplayer from the ground up. Understanding this split is critical for the networking interview question.
GAS uses a prediction key system. When a client activates an ability, it generates a key, applies local predictions, and sends the activation to the server. The server validates and either confirms or rolls back the client's predicted state.
This is why abilities feel responsive in games like Fortnite despite running on a server-authoritative model — the client doesn't wait for a server round-trip before playing animations and effects.
If clients calculated their own damage, a cheater could send arbitrary damage values. The server applies the GameplayEffect, validates the hit, computes the result, and replicates the new attribute value to all clients. Clients display what the server tells them.
| Mode | Who receives full replication | Use case |
|---|---|---|
| Full | All clients | Player characters |
| Mixed | Owner gets full, others get minimal | Player-owned actors |
| Minimal | No per-client replication | AI characters |