Gameplay Ability System (GAS)
GAS is Epic's framework for abilities, attributes, and effects with networking built in. It is
powerful but heavyweight — adopt it for games with many interacting abilities/stats; for a couple
of simple actions, plain components may be simpler.
When to use this skill
- Implementing player or enemy abilities with cooldowns, costs, and tag gating.
- Attributes (health/stamina/mana/armor) modified by buffs, debuffs, and damage.
- Networked, server-authoritative ability activation with client prediction.
- Gameplay Cues for cosmetic effects that replicate without bespoke RPCs.
- Async ability logic: waiting for animation, input, events, or delays inside an ability.
Setup
- Enable the Gameplay Abilities plugin (
.uplugin → Plugins, or add GameplayAbilitiesPlugin
to your .uproject).
- Add
"GameplayAbilities", "GameplayTags", "GameplayTasks" to your module's Build.cs
PublicDependencyModuleNames (see ue-module-and-build-system).
- Call
UAbilitySystemGlobals::Get().InitGlobalData() exactly once at startup — typically in
UAssetManager::StartInitialLoading or your game module's startup function. This is required
for target data and montage prediction; omitting it causes silent failures.
Core pieces
| Type |
Role |
UAbilitySystemComponent (ASC) |
Hub: holds granted abilities, active effects, attribute sets, owned tags |
UAttributeSet |
Declares attributes (FGameplayAttributeData) and overrides change callbacks |
UGameplayAbility |
A granted, activatable ability with cost, cooldown, and async logic |
UGameplayEffect (GE) |
Data-driven attribute/tag change: Instant, HasDuration, or Infinite |
FGameplayAbilitySpec |
A granted ability instance (class, level, input ID, source object) |
UAbilityTask |
Async step inside an ability (wait for event, montage, delay, target data) |
| Gameplay Cues |
Cosmetic feedback (VFX/SFX) keyed by GameplayCue.* tags, network-efficient |
Where the ASC lives
The ASC can sit on the Pawn or on a separate object (commonly APlayerState):
- Multiplayer player characters: ASC on the PlayerState so it survives respawn. The Pawn
implements
IAbilitySystemInterface::GetAbilitySystemComponent() returning the PlayerState's ASC.
Call ASC->InitAbilityActorInfo(OwnerActor, AvatarPawn) on the server in PossessedBy and on
the client in OnRep_PlayerState (or BeginPlay for listen-server pawns).
- AI / simple actors: ASC directly on the Pawn; call
InitAbilityActorInfo(this, this).
// Example: Pawn that delegates to PlayerState's ASC
class AMyCharacter : public ACharacter, public IAbilitySystemInterface
{
GENERATED_BODY()
public:
virtual UAbilitySystemComponent* GetAbilitySystemComponent() const override
{
if (AMyPlayerState* PS = GetPlayerState<AMyPlayerState>())
return PS->GetAbilitySystemComponent();
return nullptr;
}
};
GAS does not support a single Actor having multiple ASCs (ambiguous queries). Multiple Actors can
share one ASC (e.g. equipment routing to the character's ASC).
Attributes
Attributes are FGameplayAttributeData properties in a UAttributeSet subclass. Use the
ATTRIBUTE_ACCESSORS macro pattern (documented in AttributeSet.h:419) to generate the four
helpers: a static FGameplayAttribute getter, a float current-value getter, a setter that routes
through the ASC, and a base-value initter.
// MyAttributeSet.h
#pragma once
#include "AttributeSet.h"
#include "AbilitySystemComponent.h"
#include "MyAttributeSet.generated.h"
// Generates Get<Name>Attribute(), Get<Name>(), Set<Name>(), Init<Name>()
#define ATTRIBUTE_ACCESSORS(ClassName, PropertyName) \
GAMEPLAYATTRIBUTE_PROPERTY_GETTER(ClassName, PropertyName) \
GAMEPLAYATTRIBUTE_VALUE_GETTER(PropertyName) \
GAMEPLAYATTRIBUTE_VALUE_SETTER(PropertyName) \
GAMEPLAYATTRIBUTE_VALUE_INITTER(PropertyName)
UCLASS()
class MYGAME_API UMyAttributeSet : public UAttributeSet
{
GENERATED_BODY()
public:
// ReplicatedUsing is required for clients to see attribute changes
UPROPERTY(BlueprintReadOnly, Category="Attributes", ReplicatedUsing=OnRep_Health)
FGameplayAttributeData Health;
ATTRIBUTE_ACCESSORS(UMyAttributeSet, Health)
UPROPERTY(BlueprintReadOnly, Category="Attributes", ReplicatedUsing=OnRep_MaxHealth)
FGameplayAttributeData MaxHealth;
ATTRIBUTE_ACCESSORS(UMyAttributeSet, MaxHealth)
UFUNCTION() void OnRep_Health(const FGameplayAttributeData& OldHealth);
UFUNCTION() void OnRep_MaxHealth(const FGameplayAttributeData& OldMaxHealth);
// Clamp here; do not trigger game logic (use PostGameplayEffectExecute for that)
virtual void PreAttributeChange(const FGameplayAttribute& Attr, float& NewValue) override;
// React to confirmed changes (death, UI updates, etc.)
virtual void PostGameplayEffectExecute(const FGameplayEffectModCallbackData& Data) override;
};
Register the attribute set by creating it as a subobject on the ASC's owning actor:
// In the owning actor's constructor
AttributeSet = CreateDefaultSubobject<UMyAttributeSet>(TEXT("AttributeSet"));
The ASC auto-discovers UAttributeSet subobjects on the same actor. Never write attribute
FGameplayAttributeData fields directly at runtime — always apply a UGameplayEffect so that
prediction, replication, and aggregation work correctly.
See references/attributes-and-effects.md for PreAttributeChange
vs PostGameplayEffectExecute usage, clamping patterns, and meta-attribute (damage) patterns.
Abilities
// GA_Dash.h
UCLASS()
class MYGAME_API UGA_Dash : public UGameplayAbility
{
GENERATED_BODY()
public:
UGA_Dash();
// Primary override: do ability work here. Must call CommitAbility then EndAbility.
virtual void ActivateAbility(const FGameplayAbilitySpecHandle Handle,
const FGameplayAbilityActorInfo* ActorInfo,
const FGameplayAbilityActivationInfo ActivationInfo,
const FGameplayEventData* TriggerEventData) override;
virtual bool CanActivateAbility(const FGameplayAbilitySpecHandle Handle,
const FGameplayAbilityActorInfo* ActorInfo,
const FGameplayTagContainer* SourceTags = nullptr,
const FGameplayTagContainer* TargetTags = nullptr,
FGameplayTagContainer* OptionalRelevantTags = nullptr) const override;
};
Key ability lifecycle: CanActivateAbility (read-only check) → CommitAbility (consume cost +
cooldown) → ability logic (launch tasks) → EndAbility. Failing to call EndAbility leaves the
ability in an active state indefinitely, blocking further uses and any abilities it blocks.
Grant on server:
// Server only — GiveAbility is authority-only
FGameplayAbilitySpecHandle Handle = ASC->GiveAbility(
FGameplayAbilitySpec(UGA_Dash::StaticClass(), /*Level=*/1, /*InputID=*/INDEX_NONE));
Activate:
ASC->TryActivateAbilityByClass(UGA_Dash::StaticClass());
// or by handle:
ASC->TryActivateAbility(Handle);
Cost and cooldown are themselves UGameplayEffect assets referenced by CostGameplayEffectClass
and CooldownGameplayEffectClass on the ability. Set these in Blueprint subclasses.
See references/gameplay-abilities.md for instancing policies,
net execution policies, tag gating, FGameplayAbilitySpec fields, and event-triggered activation.
Gameplay Effects
GEs are usually data-only Blueprint assets (subclass UGameplayEffect). Choose a duration policy
(EGameplayEffectDurationType: Instant, HasDuration, Infinite), add Modifiers (attribute +
operation + magnitude), and optionally add GE Components (grants/requires/removes tags, immunity,
stacking). Apply from C++:
// Apply a damage GE from one ASC to another
FGameplayEffectContextHandle Ctx = SourceASC->MakeEffectContext();
Ctx.AddSourceObject(this);
FGameplayEffectSpecHandle Spec = SourceASC->MakeOutgoingSpec(
DamageEffectClass, /*Level=*/1.f, Ctx);
if (Spec.IsValid())
{
SourceASC->ApplyGameplayEffectSpecToTarget(*Spec.Data.Get(), TargetASC);
}
UGameplayEffect became component-based in 5.3 (UGameplayEffectComponent subclasses). The
legacy monolithic properties still work but new behavior is authored via GE Components. See
references/attributes-and-effects.md for GE Components,
execution calculations, and stacking.
Ability Tasks
Tasks handle async steps inside an ability. Use NewAbilityTask<T> (not NewObject) and call
ReadyForActivation() to start it. Always override OnDestroy to unregister callbacks.
// Inside ActivateAbility — wait for a montage notify then end
void UGA_Dash::ActivateAbility(...)
{
if (!CommitAbility(Handle, ActorInfo, ActivationInfo)) { EndAbility(...); return; }
UAbilityTask_PlayMontageAndWait* Task =
UAbilityTask_PlayMontageAndWait::CreatePlayMontageAndWaitProxy(
this, NAME_None, DashMontage);
Task->OnCompleted.AddDynamic(this, &UGA_Dash::OnMontageCompleted);
Task->OnCancelled.AddDynamic(this, &UGA_Dash::OnMontageCancelled);
Task->ReadyForActivation();
}
void UGA_Dash::OnMontageCompleted()
{
EndAbility(CurrentSpecHandle, CurrentActorInfo, CurrentActivationInfo,
/*bReplicateEndAbility=*/true, /*bWasCancelled=*/false);
}
Common built-in tasks: UAbilityTask_WaitDelay, UAbilityTask_PlayMontageAndWait,
UAbilityTask_WaitGameplayEvent, UAbilityTask_WaitTargetData,
UAbilityTask_WaitAttributeChange. All live under
Abilities/Tasks/ in the plugin's Public folder.
See references/ability-tasks-and-cues.md for custom task
authoring, NewAbilityTask, output delegate patterns, and Gameplay Cues.
Gameplay Cues
Cues are cosmetic effects (particles, sounds, decals) driven by GameplayCue.* tags. They do not
need bespoke RPCs — the ASC handles replication automatically.
// Fire a one-shot cue (e.g. impact spark)
ASC->ExecuteGameplayCue(FGameplayTag::RequestGameplayTag("GameplayCue.Impact.Spark"), Ctx);
// Add a persistent cue (e.g. burning aura) and remove it later
ASC->AddGameplayCue(FGameplayTag::RequestGameplayTag("GameplayCue.Status.Burning"), Ctx);
ASC->RemoveGameplayCue(FGameplayTag::RequestGameplayTag("GameplayCue.Status.Burning"));
Cue handlers are UGameplayCueNotify_Static (one-shot, OnExecute) or
UGameplayCueNotify_Actor (spawns an actor, OnActive/WhileActive/OnRemove). Must be tagged
GameplayCue.* and registered with the GameplayCue manager (auto-scanned from configured paths).
Networking model
- The server is authoritative. Grant/remove abilities server-only; effects apply server-side.
- Set replication mode on the ASC:
Full (single-player or small peer-to-peer), Mixed
(player-owned ASC in multiplayer), Minimal (AI-owned ASC).
- Abilities with
LocalPredicted net execution policy run immediately on the predicting client
and are confirmed or rolled back by the server. Use Gameplay Cues for cosmetic output — they
replicate without blocking server authority.
- Replicated attributes require
ReplicatedUsing=OnRep_<Name> and DOREPLIFETIME_CONDITION in
GetLifetimeReplicatedProps (handled automatically by the ASC for attribute sets it owns, but
you must implement GetLifetimeReplicatedProps on the attribute set).
Gotchas
InitGlobalData() not called — montage and target-data prediction break silently.
- Writing attribute fields directly at runtime — bypasses replication, prediction, and
aggregation. Always go through Gameplay Effects.
- ASC on Pawn for a respawning multiplayer player — state resets on death; put it on
APlayerState.
- Missing module deps (
GameplayAbilities/GameplayTags/GameplayTasks) — link errors.
EndAbility not called — the ability stays "active" forever, blocking further uses.
NonInstanced removed in 5.5 — UE_DEPRECATED_FORGAME(5.5, ...) in 5.8; use
InstancedPerActor as the default.
- Wrong replication mode —
Mixed required for player-owned ASCs in multiplayer;
Minimal-mode ASCs won't replicate GE data to simulated proxies.
- Cue tags not prefixed
GameplayCue. — the manager won't find or route them.
- Forgot to call
CommitAbility — cost/cooldown not consumed; server may reject prediction.
FindOrAddComponent/AddComponent in a GE constructor — NewObject with an empty name
fatal-asserts at CDO construction and kills the editor at module load. Use
CreateDefaultSubobject + GEComponents.Add instead (see
references/attributes-and-effects.md).
- SetByCaller cost/cooldown with bare
CommitAbility — the magnitude is never set, so the
spec applies at 0 with a warning. Override ApplyCost/ApplyCooldown (see
references/gameplay-abilities.md).
- No
GameplayCueNotifyPaths configured — the cue manager falls back to scanning all of
/Game/ (startup warning + scan cost). Set
[/Script/GameplayAbilities.AbilitySystemGlobals] +GameplayCueNotifyPaths=/Game/GameplayCues.
Version notes
NonInstanced policy deprecated in 5.5; InstancedPerActor is the recommended default.
AbilityTags deprecated in 5.5: read GetAssetTags(), set defaults with SetAssetTags(...)
(constructor only).
UGameplayEffect became component-based in 5.3 (EGameplayEffectVersion::Modular53). Legacy
monolithic GE data still works but new functionality is via UGameplayEffectComponent subclasses.
GetAbilitySystemComponentFromActorInfo_Checked() deprecated in 5.5; use
GetAbilitySystemComponentFromActorInfo_Ensured().
References & source material
Engine source (UE 5.8, Engine/Plugins/Runtime/GameplayAbilities/Source/GameplayAbilities/Public/):
AbilitySystemComponent.h — UAbilitySystemComponent: GiveAbility:949,
TryActivateAbility:1040, TryActivateAbilityByClass:1032, InitAbilityActorInfo:1523,
MakeOutgoingSpec:372, MakeEffectContext:376, ApplyGameplayEffectSpecToTarget:339,
SetReplicationMode:268, ExecuteGameplayCue:887, AddGameplayCue:891, RemoveGameplayCue:898,
EGameplayEffectReplicationMode enum:81.
AttributeSet.h — UAttributeSet:185, FGameplayAttributeData:21,
PreAttributeChange:220, PostGameplayEffectExecute:206, ATTRIBUTE_ACCESSORS pattern:419,
GAMEPLAYATTRIBUTE_PROPERTY_GETTER:428, GAMEPLAYATTRIBUTE_VALUE_GETTER:435.
Abilities/GameplayAbility.h — UGameplayAbility:91, ActivateAbility:574,
CommitAbility:336, EndAbility:604, CanActivateAbility:263, CancelAbility:299,
EGameplayAbilityInstancingPolicy:37, EGameplayAbilityNetExecutionPolicy:59
(in Abilities/GameplayAbilityTypes.h).
GameplayAbilitySpec.h — FGameplayAbilitySpec:168 (class, level, InputID, handle).
GameplayEffect.h — UGameplayEffect, EGameplayEffectDurationType:686
(Instant/Infinite/HasDuration), EGameplayEffectVersion:95 (Modular53).
AbilitySystemInterface.h — IAbilitySystemInterface::GetAbilitySystemComponent():30.
AbilitySystemGlobals.h — UAbilitySystemGlobals::InitGlobalData():69.
Abilities/Tasks/AbilityTask.h — UAbilityTask:90, NewAbilityTask<T>:136.
GameplayCueNotify_Static.h — UGameplayCueNotify_Static:19.
GameplayCueNotify_Actor.h — AGameplayCueNotify_Actor (actor-spawning cue notify):20.
Related skills: ue-gameplay-tags (GAS is tag-driven throughout), ue-networking-and-replication,
ue-animation-system (montage tasks).
Official docs (UE 5.8):
Deep-dive references in this skill:
- references/ability-system-component.md — ASC setup,
InitAbilityActorInfo, IAbilitySystemInterface, attribute set registration, replication modes.
- references/gameplay-abilities.md — ability lifecycle,
instancing policies, net execution policies, tag gating,
FGameplayAbilitySpec, Gameplay Events.
- references/attributes-and-effects.md —
FGameplayAttributeData,
attribute callbacks, GE Components, modifiers, execution calculations, stacking, meta-attributes.
- references/ability-tasks-and-cues.md — built-in tasks,
custom task authoring, output delegates, Gameplay Cue types and routing.
1---2name: ue-gameplay-ability-system3description: Build abilities, attributes, and effects with Unreal's Gameplay Ability System (GAS) — UAbilitySystemComponent (ASC), UGameplayAbility with ActivateAbility/CommitAbility/EndAbility, UAttributeSet with FGameplayAttributeData and ATTRIBUTE_ACCESSORS macro, UGameplayEffect with Instant/HasDuration/Infinite policies and GE Components, FGameplayAbilitySpec for granting, UAbilityTask for async steps (WaitDelay, PlayMontageAndWait, WaitGameplayEvent), GameplayCues for networked VFX/SFX, instancing policies (InstancedPerActor/InstancedPerExecution), net execution policies (LocalPredicted/ServerOnly), and replication modes (Full/Mixed/Minimal). Use when implementing abilities with cooldowns/costs/tags, health/stamina/mana attributes, buffs/debuffs/ damage via Gameplay Effects, ability tasks for async gameplay, Gameplay Cues for cosmetic feedback, or networked server-authoritative ability activation with client prediction. GAS requires the GameplayAbilities plugin and AbilitySystemGlobals initialization.4---56# Gameplay Ability System (GAS)78GAS is Epic's framework for abilities, attributes, and effects with networking built in. It is9powerful but heavyweight — adopt it for games with many interacting abilities/stats; for a couple10of simple actions, plain components may be simpler.1112## When to use this skill1314- Implementing player or enemy abilities with cooldowns, costs, and tag gating.15- Attributes (health/stamina/mana/armor) modified by buffs, debuffs, and damage.16- Networked, server-authoritative ability activation with client prediction.17- Gameplay Cues for cosmetic effects that replicate without bespoke RPCs.18- Async ability logic: waiting for animation, input, events, or delays inside an ability.1920## Setup21221. Enable the **Gameplay Abilities** plugin (`.uplugin` → Plugins, or add `GameplayAbilitiesPlugin`23 to your `.uproject`).242. Add `"GameplayAbilities"`, `"GameplayTags"`, `"GameplayTasks"` to your module's `Build.cs`25 `PublicDependencyModuleNames` (see `ue-module-and-build-system`).263. Call `UAbilitySystemGlobals::Get().InitGlobalData()` exactly once at startup — typically in27 `UAssetManager::StartInitialLoading` or your game module's startup function. This is required28 for target data and montage prediction; omitting it causes silent failures.2930## Core pieces3132| Type | Role |33|---|---|34| `UAbilitySystemComponent` (ASC) | Hub: holds granted abilities, active effects, attribute sets, owned tags |35| `UAttributeSet` | Declares attributes (`FGameplayAttributeData`) and overrides change callbacks |36| `UGameplayAbility` | A granted, activatable ability with cost, cooldown, and async logic |37| `UGameplayEffect` (GE) | Data-driven attribute/tag change: Instant, HasDuration, or Infinite |38| `FGameplayAbilitySpec` | A granted ability instance (class, level, input ID, source object) |39| `UAbilityTask` | Async step inside an ability (wait for event, montage, delay, target data) |40| Gameplay Cues | Cosmetic feedback (VFX/SFX) keyed by `GameplayCue.*` tags, network-efficient |4142## Where the ASC lives4344The ASC can sit on the Pawn or on a separate object (commonly `APlayerState`):4546- **Multiplayer player characters:** ASC on the **PlayerState** so it survives respawn. The Pawn47 implements `IAbilitySystemInterface::GetAbilitySystemComponent()` returning the PlayerState's ASC.48 Call `ASC->InitAbilityActorInfo(OwnerActor, AvatarPawn)` on the server in `PossessedBy` and on49 the client in `OnRep_PlayerState` (or `BeginPlay` for listen-server pawns).50- **AI / simple actors:** ASC directly on the Pawn; call `InitAbilityActorInfo(this, this)`.5152```cpp53// Example: Pawn that delegates to PlayerState's ASC54class AMyCharacter : public ACharacter, public IAbilitySystemInterface55{56 GENERATED_BODY()57public:58 virtual UAbilitySystemComponent* GetAbilitySystemComponent() const override59 {60 if (AMyPlayerState* PS = GetPlayerState<AMyPlayerState>())61 return PS->GetAbilitySystemComponent();62 return nullptr;63 }64};65```6667GAS does not support a single Actor having multiple ASCs (ambiguous queries). Multiple Actors can68share one ASC (e.g. equipment routing to the character's ASC).6970## Attributes7172Attributes are `FGameplayAttributeData` properties in a `UAttributeSet` subclass. Use the73`ATTRIBUTE_ACCESSORS` macro pattern (documented in `AttributeSet.h:419`) to generate the four74helpers: a static `FGameplayAttribute` getter, a float current-value getter, a setter that routes75through the ASC, and a base-value initter.7677```cpp78// MyAttributeSet.h79#pragma once80#include "AttributeSet.h"81#include "AbilitySystemComponent.h"82#include "MyAttributeSet.generated.h"8384// Generates Get<Name>Attribute(), Get<Name>(), Set<Name>(), Init<Name>()85#define ATTRIBUTE_ACCESSORS(ClassName, PropertyName) \86 GAMEPLAYATTRIBUTE_PROPERTY_GETTER(ClassName, PropertyName) \87 GAMEPLAYATTRIBUTE_VALUE_GETTER(PropertyName) \88 GAMEPLAYATTRIBUTE_VALUE_SETTER(PropertyName) \89 GAMEPLAYATTRIBUTE_VALUE_INITTER(PropertyName)9091UCLASS()92class MYGAME_API UMyAttributeSet : public UAttributeSet93{94 GENERATED_BODY()95public:96 // ReplicatedUsing is required for clients to see attribute changes97 UPROPERTY(BlueprintReadOnly, Category="Attributes", ReplicatedUsing=OnRep_Health)98 FGameplayAttributeData Health;99 ATTRIBUTE_ACCESSORS(UMyAttributeSet, Health)100101 UPROPERTY(BlueprintReadOnly, Category="Attributes", ReplicatedUsing=OnRep_MaxHealth)102 FGameplayAttributeData MaxHealth;103 ATTRIBUTE_ACCESSORS(UMyAttributeSet, MaxHealth)104105 UFUNCTION() void OnRep_Health(const FGameplayAttributeData& OldHealth);106 UFUNCTION() void OnRep_MaxHealth(const FGameplayAttributeData& OldMaxHealth);107108 // Clamp here; do not trigger game logic (use PostGameplayEffectExecute for that)109 virtual void PreAttributeChange(const FGameplayAttribute& Attr, float& NewValue) override;110 // React to confirmed changes (death, UI updates, etc.)111 virtual void PostGameplayEffectExecute(const FGameplayEffectModCallbackData& Data) override;112};113```114115Register the attribute set by creating it as a subobject on the ASC's owning actor:116```cpp117// In the owning actor's constructor118AttributeSet = CreateDefaultSubobject<UMyAttributeSet>(TEXT("AttributeSet"));119```120The ASC auto-discovers `UAttributeSet` subobjects on the same actor. Never write attribute121`FGameplayAttributeData` fields directly at runtime — always apply a `UGameplayEffect` so that122prediction, replication, and aggregation work correctly.123124See [references/attributes-and-effects.md](references/attributes-and-effects.md) for `PreAttributeChange`125vs `PostGameplayEffectExecute` usage, clamping patterns, and meta-attribute (damage) patterns.126127## Abilities128129```cpp130// GA_Dash.h131UCLASS()132class MYGAME_API UGA_Dash : public UGameplayAbility133{134 GENERATED_BODY()135public:136 UGA_Dash();137138 // Primary override: do ability work here. Must call CommitAbility then EndAbility.139 virtual void ActivateAbility(const FGameplayAbilitySpecHandle Handle,140 const FGameplayAbilityActorInfo* ActorInfo,141 const FGameplayAbilityActivationInfo ActivationInfo,142 const FGameplayEventData* TriggerEventData) override;143144 virtual bool CanActivateAbility(const FGameplayAbilitySpecHandle Handle,145 const FGameplayAbilityActorInfo* ActorInfo,146 const FGameplayTagContainer* SourceTags = nullptr,147 const FGameplayTagContainer* TargetTags = nullptr,148 FGameplayTagContainer* OptionalRelevantTags = nullptr) const override;149};150```151152Key ability lifecycle: `CanActivateAbility` (read-only check) → `CommitAbility` (consume cost +153cooldown) → ability logic (launch tasks) → `EndAbility`. Failing to call `EndAbility` leaves the154ability in an active state indefinitely, blocking further uses and any abilities it blocks.155156**Grant on server:**157```cpp158// Server only — GiveAbility is authority-only159FGameplayAbilitySpecHandle Handle = ASC->GiveAbility(160 FGameplayAbilitySpec(UGA_Dash::StaticClass(), /*Level=*/1, /*InputID=*/INDEX_NONE));161```162163**Activate:**164```cpp165ASC->TryActivateAbilityByClass(UGA_Dash::StaticClass());166// or by handle:167ASC->TryActivateAbility(Handle);168```169170Cost and cooldown are themselves `UGameplayEffect` assets referenced by `CostGameplayEffectClass`171and `CooldownGameplayEffectClass` on the ability. Set these in Blueprint subclasses.172173See [references/gameplay-abilities.md](references/gameplay-abilities.md) for instancing policies,174net execution policies, tag gating, `FGameplayAbilitySpec` fields, and event-triggered activation.175176## Gameplay Effects177178GEs are usually data-only Blueprint assets (subclass `UGameplayEffect`). Choose a duration policy179(`EGameplayEffectDurationType`: `Instant`, `HasDuration`, `Infinite`), add Modifiers (attribute +180operation + magnitude), and optionally add GE Components (grants/requires/removes tags, immunity,181stacking). Apply from C++:182183```cpp184// Apply a damage GE from one ASC to another185FGameplayEffectContextHandle Ctx = SourceASC->MakeEffectContext();186Ctx.AddSourceObject(this);187FGameplayEffectSpecHandle Spec = SourceASC->MakeOutgoingSpec(188 DamageEffectClass, /*Level=*/1.f, Ctx);189if (Spec.IsValid())190{191 SourceASC->ApplyGameplayEffectSpecToTarget(*Spec.Data.Get(), TargetASC);192}193```194195`UGameplayEffect` became component-based in 5.3 (`UGameplayEffectComponent` subclasses). The196legacy monolithic properties still work but new behavior is authored via GE Components. See197[references/attributes-and-effects.md](references/attributes-and-effects.md) for GE Components,198execution calculations, and stacking.199200## Ability Tasks201202Tasks handle async steps inside an ability. Use `NewAbilityTask<T>` (not `NewObject`) and call203`ReadyForActivation()` to start it. Always override `OnDestroy` to unregister callbacks.204205```cpp206// Inside ActivateAbility — wait for a montage notify then end207void UGA_Dash::ActivateAbility(...)208{209 if (!CommitAbility(Handle, ActorInfo, ActivationInfo)) { EndAbility(...); return; }210211 UAbilityTask_PlayMontageAndWait* Task =212 UAbilityTask_PlayMontageAndWait::CreatePlayMontageAndWaitProxy(213 this, NAME_None, DashMontage);214 Task->OnCompleted.AddDynamic(this, &UGA_Dash::OnMontageCompleted);215 Task->OnCancelled.AddDynamic(this, &UGA_Dash::OnMontageCancelled);216 Task->ReadyForActivation();217}218219void UGA_Dash::OnMontageCompleted()220{221 EndAbility(CurrentSpecHandle, CurrentActorInfo, CurrentActivationInfo,222 /*bReplicateEndAbility=*/true, /*bWasCancelled=*/false);223}224```225226Common built-in tasks: `UAbilityTask_WaitDelay`, `UAbilityTask_PlayMontageAndWait`,227`UAbilityTask_WaitGameplayEvent`, `UAbilityTask_WaitTargetData`,228`UAbilityTask_WaitAttributeChange`. All live under229`Abilities/Tasks/` in the plugin's Public folder.230231See [references/ability-tasks-and-cues.md](references/ability-tasks-and-cues.md) for custom task232authoring, `NewAbilityTask`, output delegate patterns, and Gameplay Cues.233234## Gameplay Cues235236Cues are cosmetic effects (particles, sounds, decals) driven by `GameplayCue.*` tags. They do not237need bespoke RPCs — the ASC handles replication automatically.238239```cpp240// Fire a one-shot cue (e.g. impact spark)241ASC->ExecuteGameplayCue(FGameplayTag::RequestGameplayTag("GameplayCue.Impact.Spark"), Ctx);242243// Add a persistent cue (e.g. burning aura) and remove it later244ASC->AddGameplayCue(FGameplayTag::RequestGameplayTag("GameplayCue.Status.Burning"), Ctx);245ASC->RemoveGameplayCue(FGameplayTag::RequestGameplayTag("GameplayCue.Status.Burning"));246```247248Cue handlers are `UGameplayCueNotify_Static` (one-shot, `OnExecute`) or249`UGameplayCueNotify_Actor` (spawns an actor, `OnActive`/`WhileActive`/`OnRemove`). Must be tagged250`GameplayCue.*` and registered with the GameplayCue manager (auto-scanned from configured paths).251252## Networking model253254- The **server is authoritative**. Grant/remove abilities server-only; effects apply server-side.255- Set replication mode on the ASC: `Full` (single-player or small peer-to-peer), `Mixed`256 (player-owned ASC in multiplayer), `Minimal` (AI-owned ASC).257- Abilities with `LocalPredicted` net execution policy run immediately on the predicting client258 and are confirmed or rolled back by the server. Use Gameplay Cues for cosmetic output — they259 replicate without blocking server authority.260- Replicated attributes require `ReplicatedUsing=OnRep_<Name>` and `DOREPLIFETIME_CONDITION` in261 `GetLifetimeReplicatedProps` (handled automatically by the ASC for attribute sets it owns, but262 you must implement `GetLifetimeReplicatedProps` on the attribute set).263264## Gotchas265266- **`InitGlobalData()` not called** — montage and target-data prediction break silently.267- **Writing attribute fields directly** at runtime — bypasses replication, prediction, and268 aggregation. Always go through Gameplay Effects.269- **ASC on Pawn for a respawning multiplayer player** — state resets on death; put it on270 `APlayerState`.271- **Missing module deps** (`GameplayAbilities`/`GameplayTags`/`GameplayTasks`) — link errors.272- **`EndAbility` not called** — the ability stays "active" forever, blocking further uses.273- **`NonInstanced` removed in 5.5** — `UE_DEPRECATED_FORGAME(5.5, ...)` in 5.8; use274 `InstancedPerActor` as the default.275- **Wrong replication mode** — `Mixed` required for player-owned ASCs in multiplayer;276 `Minimal`-mode ASCs won't replicate GE data to simulated proxies.277- **Cue tags not prefixed `GameplayCue.`** — the manager won't find or route them.278- **Forgot to call `CommitAbility`** — cost/cooldown not consumed; server may reject prediction.279- **`FindOrAddComponent`/`AddComponent` in a GE constructor** — NewObject with an empty name280 fatal-asserts at CDO construction and kills the editor at module load. Use281 `CreateDefaultSubobject` + `GEComponents.Add` instead (see282 [references/attributes-and-effects.md](references/attributes-and-effects.md)).283- **SetByCaller cost/cooldown with bare `CommitAbility`** — the magnitude is never set, so the284 spec applies at 0 with a warning. Override `ApplyCost`/`ApplyCooldown` (see285 [references/gameplay-abilities.md](references/gameplay-abilities.md)).286- **No `GameplayCueNotifyPaths` configured** — the cue manager falls back to scanning all of287 `/Game/` (startup warning + scan cost). Set288 `[/Script/GameplayAbilities.AbilitySystemGlobals]` `+GameplayCueNotifyPaths=/Game/GameplayCues`.289290## Version notes291292- `NonInstanced` policy deprecated in 5.5; `InstancedPerActor` is the recommended default.293- `AbilityTags` deprecated in 5.5: read `GetAssetTags()`, set defaults with `SetAssetTags(...)`294 (constructor only).295- `UGameplayEffect` became component-based in 5.3 (`EGameplayEffectVersion::Modular53`). Legacy296 monolithic GE data still works but new functionality is via `UGameplayEffectComponent` subclasses.297- `GetAbilitySystemComponentFromActorInfo_Checked()` deprecated in 5.5; use298 `GetAbilitySystemComponentFromActorInfo_Ensured()`.299300## References & source material301302Engine source (UE 5.8, `Engine/Plugins/Runtime/GameplayAbilities/Source/GameplayAbilities/Public/`):303- `AbilitySystemComponent.h` — `UAbilitySystemComponent`: `GiveAbility`:949,304 `TryActivateAbility`:1040, `TryActivateAbilityByClass`:1032, `InitAbilityActorInfo`:1523,305 `MakeOutgoingSpec`:372, `MakeEffectContext`:376, `ApplyGameplayEffectSpecToTarget`:339,306 `SetReplicationMode`:268, `ExecuteGameplayCue`:887, `AddGameplayCue`:891, `RemoveGameplayCue`:898,307 `EGameplayEffectReplicationMode` enum:81.308- `AttributeSet.h` — `UAttributeSet`:185, `FGameplayAttributeData`:21,309 `PreAttributeChange`:220, `PostGameplayEffectExecute`:206, `ATTRIBUTE_ACCESSORS` pattern:419,310 `GAMEPLAYATTRIBUTE_PROPERTY_GETTER`:428, `GAMEPLAYATTRIBUTE_VALUE_GETTER`:435.311- `Abilities/GameplayAbility.h` — `UGameplayAbility`:91, `ActivateAbility`:574,312 `CommitAbility`:336, `EndAbility`:604, `CanActivateAbility`:263, `CancelAbility`:299,313 `EGameplayAbilityInstancingPolicy`:37, `EGameplayAbilityNetExecutionPolicy`:59314 (in `Abilities/GameplayAbilityTypes.h`).315- `GameplayAbilitySpec.h` — `FGameplayAbilitySpec`:168 (class, level, InputID, handle).316- `GameplayEffect.h` — `UGameplayEffect`, `EGameplayEffectDurationType`:686317 (Instant/Infinite/HasDuration), `EGameplayEffectVersion`:95 (Modular53).318- `AbilitySystemInterface.h` — `IAbilitySystemInterface::GetAbilitySystemComponent()`:30.319- `AbilitySystemGlobals.h` — `UAbilitySystemGlobals::InitGlobalData()`:69.320- `Abilities/Tasks/AbilityTask.h` — `UAbilityTask`:90, `NewAbilityTask<T>`:136.321- `GameplayCueNotify_Static.h` — `UGameplayCueNotify_Static`:19.322- `GameplayCueNotify_Actor.h` — `AGameplayCueNotify_Actor` (actor-spawning cue notify):20.323324Related skills: `ue-gameplay-tags` (GAS is tag-driven throughout), `ue-networking-and-replication`,325`ue-animation-system` (montage tasks).326327Official docs (UE 5.8):328- Gameplay Ability System — <https://dev.epicgames.com/documentation/unreal-engine/gameplay-ability-system-for-unreal-engine>329- ASC and Attributes — <https://dev.epicgames.com/documentation/unreal-engine/gameplay-ability-system-component-and-gameplay-attributes-in-unreal-engine>330- Gameplay Ability — <https://dev.epicgames.com/documentation/unreal-engine/using-gameplay-abilities-in-unreal-engine>331- Gameplay Attributes and Attribute Sets — <https://dev.epicgames.com/documentation/unreal-engine/gameplay-attributes-and-attribute-sets-for-the-gameplay-ability-system-in-unreal-engine>332- Gameplay Effects — <https://dev.epicgames.com/documentation/unreal-engine/gameplay-effects-for-the-gameplay-ability-system-in-unreal-engine>333- Ability Tasks — <https://dev.epicgames.com/documentation/unreal-engine/gameplay-ability-tasks-in-unreal-engine>334- GAS Overview — <https://dev.epicgames.com/documentation/unreal-engine/understanding-the-unreal-engine-gameplay-ability-system>335336Deep-dive references in this skill:337- [references/ability-system-component.md](references/ability-system-component.md) — ASC setup,338 `InitAbilityActorInfo`, `IAbilitySystemInterface`, attribute set registration, replication modes.339- [references/gameplay-abilities.md](references/gameplay-abilities.md) — ability lifecycle,340 instancing policies, net execution policies, tag gating, `FGameplayAbilitySpec`, Gameplay Events.341- [references/attributes-and-effects.md](references/attributes-and-effects.md) — `FGameplayAttributeData`,342 attribute callbacks, GE Components, modifiers, execution calculations, stacking, meta-attributes.343- [references/ability-tasks-and-cues.md](references/ability-tasks-and-cues.md) — built-in tasks,344 custom task authoring, output delegates, Gameplay Cue types and routing.