
ue-gameplay-abilities
Use when implementing or debugging the Gameplay Ability System in C++ — abilities, effects, attributes, cues and the AbilitySystemComponent. Also use when the user mentions 'GAS', 'UGameplayAbility', 'ActivateAbility', 'CommitAbility', 'UGameplayEffect', 'UAttributeSet', 'FGameplayAttributeData', 'AbilitySystemComponent', 'InitAbilityActorInfo', 'GiveAbility', 'TryActivateAbility', 'ability task', 'GameplayCue', 'cooldown', 'cost', 'buff', 'debuff', 'damage execution' or 'ASC on PlayerState'. For montage playback, see ue-animation-system; for replication modes and prediction, see ue-networking-replication.
- Installs
- 1.2K
- Last 24h
- +12
- Trending rank
- #8099
- Security
- Not audited
Install
Works with every agent the skills CLI supports.
npx skills add https://github.com/quodsoler/unreal-engine-skills --skill ue-gameplay-abilities- 01
Install
Run the command in your project. The CLI asks which agents to install for.
- 02
Describe the task
Ask your agent for something this skill covers. It loads ue-gameplay-abilities automatically when relevant.
- 03
Review the result
The agent follows the SKILL.md steps, scripts and references bundled with the skill.
SKILL.md
The instructions your agent reads when the skill is triggered.
UE Gameplay Ability System
Target engine: UE 5.8. APIs below are verified against the 5.8 headers; older forms are listed under "Deprecated — do not use".
GAS ships as the GameplayAbilities plugin (Engine/Plugins/Runtime/GameplayAbilities), which is production-ready, not Experimental. Enable it in the .uproject, then add "GameplayAbilities", "GameplayTags" and "GameplayTasks" to PublicDependencyModuleNames in your module's Build.cs. This skill covers UAbilitySystemComponent, UGameplayAbility, UGameplayEffect, UAttributeSet, UAbilityTask and Gameplay Cues.
Context
Read .agents/ue-project-context.md if it exists (module names, conventions, enabled plugins, GAS/networking setup). Do not stop if it is missing.
Identify the area from the request and the codebase. Ask only when two plausible readings would produce different code.
| Request is about… | Go to |
|---|---|
| Where the ASC lives, init order, respawn, replication mode | ASC Ownership and Initialization |
| Writing an ability, activation, cost, cooldown, policies | Gameplay Abilities |
| Waiting on montages, events, targeting, timers, tag queries | Ability Tasks |
| Damage, buffs, stacking, executions, immunity, GE components | Gameplay Effects |
| Health/mana floats, clamping, attribute replication | Attribute Sets |
| Tags that block, grant or cancel abilities; loose tags | Tags in GAS |
| Particles, sounds, hit impacts, cue notify classes | Gameplay Cues |
| Cue scan paths, global curve tables, project config | Project Settings |
GAS Architecture
| Pillar | Class | Header | Purpose |
|---|---|---|---|
| Component | UAbilitySystemComponent | AbilitySystemComponent.h | Owns abilities, effects, attributes, tags |
| Abilities | UGameplayAbility | Abilities/GameplayAbility.h | What happens when activated |
| Effects | UGameplayEffect | GameplayEffect.h | Data-driven attribute mutation |
| Attributes | UAttributeSet | AttributeSet.h | Replicated FGameplayAttributeData stats |
| Tasks | UAbilityTask | Abilities/Tasks/AbilityTask.h | Latent steps inside an ability |
Gameplay tags thread through all of them as requirements, grants and blockers.
ASC Ownership and Initialization
| Owner | When | Notes |
|---|---|---|
APlayerState | Networked player characters | ASC survives pawn death; use Mixed replication |
APawn / ACharacter | AI, single-player | Simplest; use Minimal for AI, Full if a pawn-owned ASC needs full data on all clients |
Every actor that owns or exposes an ASC implements IAbilitySystemInterface:
// MyCharacter.h
#pragma once
#include "GameFramework/Character.h"
#include "AbilitySystemInterface.h"
#include "MyCharacter.generated.h"
class UAbilitySystemComponent;
UCLASS()
class MYGAME_API AMyCharacter : public ACharacter, public IAbilitySystemInterface
{
GENERATED_BODY()
public:
AMyCharacter();
virtual UAbilitySystemComponent* GetAbilitySystemComponent() const override;
protected:
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "GAS")
TObjectPtr<UAbilitySystemComponent> AbilitySystemComponent;
};
// MyCharacter.cpp
#include "MyCharacter.h"
#include "AbilitySystemComponent.h"
AMyCharacter::AMyCharacter()
{
AbilitySystemComponent = CreateDefaultSubobject<UAbilitySystemComponent>(TEXT("AbilitySystemComponent"));
AbilitySystemComponent->SetIsReplicated(true);
AbilitySystemComponent->SetReplicationMode(EGameplayEffectReplicationMode::Mixed);
}
UAbilitySystemComponent* AMyCharacter::GetAbilitySystemComponent() const
{
return AbilitySystemComponent;
}
InitAbilityActorInfo(OwnerActor, AvatarActor) must run on both server and client. For a pawn-owned ASC that is BeginPlay with (this, this). For a PlayerState-owned ASC it is PossessedBy on the server and OnRep_PlayerState on the client, with (PlayerState, Character). Full dual-path code, respawn handling and the AI variant are in gas-setup-patterns.md.
EGameplayEffectReplicationMode | Effect on simulated proxies |
|---|---|
Minimal | No GE replication; minimal tag/cue data only. AI and non-player actors |
Mixed | Full GEs to the owning connection, minimal to everyone else. Player characters |
Full | Every GE replicates to every client |
Mixed sends full GE data to the connection that owns the ASC's owner actor (GameplayEffect.cpp:5240), so it works for a PlayerState-owned ASC and for a pawn-owned ASC once a PlayerController possesses the pawn. Choosing Full over Mixed is a bandwidth decision, not a correctness one. Minimal does not work for player-owned ASCs (AbilitySystemComponent.h:83). See ue-networking-replication for what each mode costs on the wire.
Gameplay Abilities
// MyFireballAbility.h
#pragma once
#include "Abilities/GameplayAbility.h"
#include "MyFireballAbility.generated.h"
class UGameplayEffect;
UCLASS()
class MYGAME_API UMyFireballAbility : public UGameplayAbility
{
GENERATED_BODY()
public:
UMyFireballAbility();
virtual bool CanActivateAbility(const FGameplayAbilitySpecHandle Handle,
const FGameplayAbilityActorInfo* ActorInfo,
const FGameplayTagContainer* SourceTags = nullptr,
const FGameplayTagContainer* TargetTags = nullptr,
OUT FGameplayTagContainer* OptionalRelevantTags = nullptr) const override;
virtual void ActivateAbility(const FGameplayAbilitySpecHandle Handle,
const FGameplayAbilityActorInfo* ActorInfo,
const FGameplayAbilityActivationInfo ActivationInfo,
const FGameplayEventData* TriggerEventData) override;
virtual void EndAbility(const FGameplayAbilitySpecHandle Handle,
const FGameplayAbilityActorInfo* ActorInfo,
const FGameplayAbilityActivationInfo ActivationInfo,
bool bReplicateEndAbility, bool bWasCancelled) override;
virtual void CancelAbility(const FGameplayAbilitySpecHandle Handle,
const FGameplayAbilityActorInfo* ActorInfo,
const FGameplayAbilityActivationInfo ActivationInfo,
bool bReplicateCancelAbility) override;
protected:
UPROPERTY(EditDefaultsOnly, Category = "GAS")
TSubclassOf<UGameplayEffect> DamageEffect;
};
Constructor sets the policies and the ability's own tags:
// MyFireballAbility.cpp
#include "MyFireballAbility.h"
#include "AbilitySystemBlueprintLibrary.h"
#include "AbilitySystemComponent.h"
UMyFireballAbility::UMyFireballAbility()
{
InstancingPolicy = EGameplayAbilityInstancingPolicy::InstancedPerActor;
NetExecutionPolicy = EGameplayAbilityNetExecutionPolicy::LocalPredicted;
NetSecurityPolicy = EGameplayAbilityNetSecurityPolicy::ClientOrServer;
FGameplayTagContainer Tags;
Tags.AddTag(FGameplayTag::RequestGameplayTag(TEXT("Ability.Skill.Fireball")));
SetAssetTags(Tags);
ActivationOwnedTags.AddTag(FGameplayTag::RequestGameplayTag(TEXT("Ability.Active.Casting")));
ActivationBlockedTags.AddTag(FGameplayTag::RequestGameplayTag(TEXT("State.Stunned")));
CancelAbilitiesWithTag.AddTag(FGameplayTag::RequestGameplayTag(TEXT("Ability.Active.Melee")));
}
SetAssetTags is constructor-only; read them back with GetAssetTags().
| Enum | Values | Use |
|---|---|---|
EGameplayAbilityInstancingPolicy | InstancedPerActor, InstancedPerExecution | InstancedPerActor is the default choice; per-execution when several copies may run at once |
EGameplayAbilityNetExecutionPolicy | LocalPredicted, LocalOnly, ServerInitiated, ServerOnly | LocalPredicted for responsive player abilities |
EGameplayAbilityNetSecurityPolicy | ClientOrServer, ServerOnlyExecution, ServerOnlyTermination, ServerOnly | Rejects client requests the server should own |
void UMyFireballAbility::ActivateAbility(const FGameplayAbilitySpecHandle Handle,
const FGameplayAbilityActorInfo* ActorInfo,
const FGameplayAbilityActivationInfo ActivationInfo,
const FGameplayEventData* TriggerEventData)
{
Super::ActivateAbility(Handle, ActorInfo, ActivationInfo, TriggerEventData);
// CommitAbility applies cost and cooldown; it fails if either cannot be paid.
if (!CommitAbility(Handle, ActorInfo, ActivationInfo))
{
EndAbility(Handle, ActorInfo, ActivationInfo, true, true);
return;
}
const FGameplayEffectSpecHandle Spec =
MakeOutgoingGameplayEffectSpec(DamageEffect, GetAbilityLevel());
const FGameplayAbilityTargetDataHandle TargetData =
UAbilitySystemBlueprintLibrary::AbilityTargetDataFromActor(ActorInfo->AvatarActor.Get());
ApplyGameplayEffectSpecToTarget(Handle, ActorInfo, ActivationInfo, Spec, TargetData);
EndAbility(Handle, ActorInfo, ActivationInfo, true, false);
}
Split the commit when the two halves must happen at different times: CommitAbilityCost(Handle, ActorInfo, ActivationInfo) and CommitAbilityCooldown(Handle, ActorInfo, ActivationInfo, ForceCooldown) — note the cooldown overload takes the extra const bool ForceCooldown.
Inside an instanced ability, GetAbilitySystemComponentFromActorInfo_Ensured() returns the ASC and logs an ensure instead of crashing when actor info is not set up.
Granting and activating, from the server:
const FGameplayAbilitySpecHandle Handle =
ASC->GiveAbility(FGameplayAbilitySpec(UMyFireballAbility::StaticClass(), 1));
ASC->TryActivateAbility(Handle);
ASC->TryActivateAbilityByClass(UMyFireballAbility::StaticClass());
ASC->TryActivateAbilitiesByTag(
FGameplayTagContainer(FGameplayTag::RequestGameplayTag(TEXT("Ability.Skill.Fireball"))));
ASC->ClearAbility(Handle);
Ability Tasks
Ability tasks make an ability span frames. The pattern is always: static factory → bind delegates → ReadyForActivation() (inherited from UGameplayTask). Task delegates are dynamic, so each handler needs UFUNCTION():
// In the ability's header:
UFUNCTION()
void HandleMontageCompleted();
UFUNCTION()
void HandleMontageInterrupted();
#include "Abilities/Tasks/AbilityTask_PlayMontageAndWait.h"
UAbilityTask_PlayMontageAndWait* Task =
UAbilityTask_PlayMontageAndWait::CreatePlayMontageAndWaitProxy(
this, NAME_None, AttackMontage, 1.f);
Task->OnCompleted.AddDynamic(this, &UMyFireballAbility::HandleMontageCompleted);
Task->OnInterrupted.AddDynamic(this, &UMyFireballAbility::HandleMontageInterrupted);
Task->ReadyForActivation();
| Task | Waits for |
|---|---|
UAbilityTask_PlayMontageAndWait | An UAnimMontage to finish, blend out, interrupt or cancel |
UAbilityTask_PlayAnimAndWait | A raw UAnimSequence played into a slot, for linked anim layers |
UAbilityTask_WaitGameplayEvent | A gameplay event tag sent to the ASC (anim notify, hit registration) |
UAbilityTask_WaitDelay | A fixed number of seconds |
UAbilityTask_WaitTargetData | An AGameplayAbilityTargetActor to confirm targets |
UAbilityTask_WaitAttributeChange / ...ChangeThreshold | An attribute to change or cross a comparison |
UAbilityTask_WaitGameplayTagQuery | An FGameplayTagQuery over the target's tags to become true or false |
UAbilityTask_WaitGameplayTagCountChanged | The count of one tag on the ASC to change |
UAbilityTask_WaitGameplayEffectApplied_Self / _Target | A GE matching tag requirements (or an FGameplayTagQuery via the _Query factories) |
Full factory signatures, delegate names, the custom-task template and the task pitfalls are in ability-task-reference.md.
Gameplay Effects
EGameplayEffectDurationType | Behaviour |
|---|---|
Instant | Executes once against the base value; fires PostGameplayEffectExecute |
HasDuration | Aggregates onto the current value for DurationMagnitude seconds |
Infinite | Aggregates until removed explicitly |
const FGameplayEffectContextHandle Ctx = ASC->MakeEffectContext();
const FGameplayEffectSpecHandle Spec =
ASC->MakeOutgoingSpec(UMyDamageEffect::StaticClass(), Level, Ctx);
Spec.Data->SetSetByCallerMagnitude(
FGameplayTag::RequestGameplayTag(TEXT("SetByCaller.Damage")), 75.f);
ASC->ApplyGameplayEffectSpecToSelf(*Spec.Data.Get());
ASC->ApplyGameplayEffectSpecToTarget(*Spec.Data.Get(), TargetASC);
ASC->RemoveActiveGameplayEffect(ActiveHandle);
ASC->RemoveActiveGameplayEffectBySourceEffect(UMyDamageEffect::StaticClass(), nullptr);
Modifier ops live in EGameplayModOp (a namespaced enum, so values are TEnumAsByte<EGameplayModOp::Type>). The aggregation equation is
((BaseValue + AddBase) * MultiplyAdditive / DivideAdditive * MultiplyCompound) + AddFinal.
| Value | Meaning |
|---|---|
AddBase | Added to the base before anything else |
MultiplyAdditive | Multipliers summed, then multiplied against the running result |
DivideAdditive | Divisors summed, then divided against the running result |
MultiplyCompound | Multiplied into the running result, compounding with other compounds |
AddFinal | Added after all multiplication |
Override | Replaces the computed value |
Behaviour that used to be monolithic properties on UGameplayEffect now lives in UGameplayEffectComponent subclasses under GameplayEffectComponents/. Stacking, magnitude calculations, UGameplayEffectExecutionCalculation, periodic effects, immunity, queries, lifecycle delegates and the full component list are in gameplay-effect-reference.md.
Attribute Sets
// MyHealthSet.h
#pragma once
#include "AttributeSet.h"
#include "AbilitySystemComponent.h"
#include "MyHealthSet.generated.h"
UCLASS()
class MYGAME_API UMyHealthSet : public UAttributeSet
{
GENERATED_BODY()
public:
UMyHealthSet();
virtual void PreAttributeChange(const FGameplayAttribute& Attribute, float& NewValue) override;
virtual void PostGameplayEffectExecute(const struct FGameplayEffectModCallbackData& Data) override;
virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;
UPROPERTY(BlueprintReadOnly, ReplicatedUsing = OnRep_Health, Category = "Health")
FGameplayAttributeData Health;
ATTRIBUTE_ACCESSORS_BASIC(UMyHealthSet, Health)
UPROPERTY(BlueprintReadOnly, ReplicatedUsing = OnRep_MaxHealth, Category = "Health")
FGameplayAttributeData MaxHealth;
ATTRIBUTE_ACCESSORS_BASIC(UMyHealthSet, MaxHealth)
protected:
UFUNCTION()
void OnRep_Health(const FGameplayAttributeData& OldHealth);
UFUNCTION()
void OnRep_MaxHealth(const FGameplayAttributeData& OldMaxHealth);
};
ATTRIBUTE_ACCESSORS_BASIC generates GetHealthAttribute(), GetHealth(), SetHealth() and InitHealth(). Projects that want extra accessors define their own macro chaining GAMEPLAYATTRIBUTE_PROPERTY_GETTER, GAMEPLAYATTRIBUTE_VALUE_GETTER, GAMEPLAYATTRIBUTE_VALUE_SETTER and GAMEPLAYATTRIBUTE_VALUE_INITTER.
Each OnRep_ body is one GAMEPLAYATTRIBUTE_REPNOTIFY(UMyHealthSet, Health, OldHealth) call, and every attribute needs a DOREPLIFETIME_CONDITION_NOTIFY(UMyHealthSet, Health, COND_None, REPNOTIFY_Always) line. The full .cpp with clamping is in gas-setup-patterns.md.
| Hook | Fires | Use for |
|---|---|---|
PreAttributeChange | Every current-value recompute | Clamping the current value only |
PreAttributeBaseChange | Before a base-value write (const) | Clamping the base value |
PostGameplayEffectExecute | After an instant GE, or one period of a periodic GE, writes the base value | Death, hit reactions, game events |
PostAttributeChange | After a current value changed | Reacting to derived state |
Registering and reading:
// Constructor of the ASC owner — the ASC finds subobject attribute sets automatically:
HealthSet = CreateDefaultSubobject<UMyHealthSet>(TEXT("HealthSet"));
// Runtime, authority only:
UMyHealthSet* NewSet = NewObject<UMyHealthSet>(this);
ASC->AddSpawnedAttribute(NewSet);
const float CurrentHealth = ASC->GetNumericAttribute(UMyHealthSet::GetHealthAttribute());
One ASC can host several UAttributeSet subclasses, but only one instance per class.
Tags in GAS
Tag definition (native tag macros, .ini tag sources), container matching and FGameplayTagQuery semantics belong to ue-gameplay-tags-messaging. What is GAS-specific:
// On the ability CDO (constructor): tags granted while the ability runs, and the gates.
ActivationOwnedTags.AddTag(CastingTag);
ActivationRequiredTags.AddTag(WeaponEquippedTag);
ActivationBlockedTags.AddTag(StunnedTag);
BlockAbilitiesWithTag.AddTag(MeleeTag);
CancelAbilitiesWithTag.AddTag(ChannelTag);
// On the ASC: query and react.
ASC->HasMatchingGameplayTag(StunnedTag);
const FGameplayTagContainer& Owned = ASC->GetOwnedGameplayTags();
ASC->RegisterGameplayTagEvent(StunnedTag, EGameplayTagEventType::NewOrRemoved)
.AddUObject(this, &AMyCharacter::HandleStunnedTagChanged);
The callback is declared as void HandleStunnedTagChanged(const FGameplayTag Tag, int32 NewCount); and needs no UFUNCTION() — tag events are plain multicast delegates.
Loose tags are set directly instead of through a GE. The third argument chooses how the tag replicates:
ASC->AddLooseGameplayTag(StunnedTag); // local only
ASC->AddLooseGameplayTag(BuffedTag, 1, EGameplayTagReplicationState::TagOnly); // tag to all
ASC->AddLooseGameplayTag(BuffedTag, 1, EGameplayTagReplicationState::CountToOwner);// + count to owner
ASC->RemoveLooseGameplayTag(BuffedTag, 1, EGameplayTagReplicationState::TagOnly);
ASC->SetLooseGameplayTagCount(BuffedTag, 3, EGameplayTagReplicationState::TagAndCountToAll);
EGameplayTagReplicationState values: None, SimulatedTagOnly, TagOnly, CountToOwner, TagAndCountToAll. Anything other than None must be added on the server.
Gameplay Cues
Cues are cosmetic only. Tag prefix GameplayCue.; a GE triggers them through its GameplayCues array, or code fires them directly:
ASC->ExecuteGameplayCue(HitCueTag, ASC->MakeEffectContext()); // one-shot
ASC->AddGameplayCue(BuffCueTag); // persistent
ASC->RemoveGameplayCue(BuffCueTag);
const bool bActive = ASC->IsGameplayCueActive(BuffCueTag);
| Class | Base | Override | Use |
|---|---|---|---|
UGameplayCueNotify_Static | UObject | OnExecute_Implementation | Burst cue with no spawned actor |
UGameplayCueNotify_Burst | UGameplayCueNotify_Static | data-driven burst effects | One-shot particles/sounds, no code |
UGameplayCueNotify_HitImpact | UGameplayCueNotify_Static | data-driven impact effects | Surface-typed impacts |
AGameplayCueNotify_Actor | AActor | OnActive_/WhileActive_/OnRemove_Implementation | Persistent cue needing an actor |
AGameplayCueNotify_BurstLatent | AGameplayCueNotify_Actor | data-driven burst effects | Burst that must spawn an actor |
AGameplayCueNotify_Looping | AGameplayCueNotify_Actor | data-driven looping effects | Looping auras and channels |
// MyHitCue.h
#pragma once
#include "GameplayCueNotify_Static.h"
#include "MyHitCue.generated.h"
UCLASS()
class MYGAME_API UMyHitCue : public UGameplayCueNotify_Static
{
GENERATED_BODY()
public:
virtual bool OnExecute_Implementation(AActor* MyTarget,
const FGameplayCueParameters& Parameters) const override;
};
UGameplayCueManager discovers cue assets under the scan paths configured in project settings.
Project Settings
GAS configuration is a UDeveloperSettings class: UGameplayAbilitiesDeveloperSettings (Project Settings → Gameplay Abilities). Read it with GetDefault<UGameplayAbilitiesDeveloperSettings>(). Notable fields: GameplayCueNotifyPaths, ReplicateActivationOwnedTags, bAllowGameplayModEvaluationChannels, plus the global curve/attribute tables. Runtime helpers stay on UAbilitySystemGlobals (GetGameplayCueNotifyPaths(), AddGameplayCueNotifyPath(), GetAttributeSetInitter()).
Deprecated — do not use
| Do not emit | Use in 5.8 | Source |
|---|---|---|
AGameplayCueNotify_Static | UGameplayCueNotify_Static (a UObject) | Class never existed; GameplayCueNotify_Static.h:19 |
EGameplayModOp::Multiplicative | EGameplayModOp::MultiplyAdditive (legacy alias is spelled Multiplicitive) | GameplayEffectTypes.h:112-148 |
EGameplayModOp::Additive / Division | AddBase / DivideAdditive | Hidden back-compat aliases, GameplayEffectTypes.h:141-143 |
EGameplayAbilityInstancingPolicy::NonInstanced | InstancedPerActor | UE_DEPRECATED_FORGAME(5.5) in Abilities/GameplayAbilityTypes.h:46 |
UGameplayAbility::AbilityTags | GetAssetTags() / SetAssetTags() | UE_DEPRECATED_FORGAME(5.5) in Abilities/GameplayAbility.h:474 |
GetAbilitySystemComponentFromActorInfo_Checked() | GetAbilitySystemComponentFromActorInfo_Ensured() | UE_DEPRECATED(5.5) in Abilities/GameplayAbility.h:168 |
NetUpdateFrequency assignment on an actor | SetNetUpdateFrequency(100.f) | UE_DEPRECATED(5.5) in GameFramework/Actor.h:903 |
UGameplayEffect::StackingType (public read) | GetStackingType() | UE_DEPRECATED(5.7) in GameplayEffect.h:2407 |
UGameplayEffect::GrantedApplicationImmunityTags | UImmunityGameplayEffectComponent | UE_DEPRECATED(5.3) in GameplayEffect.h:2379 |
AddReplicatedLooseGameplayTag | AddLooseGameplayTag(Tag, Count, EGameplayTagReplicationState::CountToOwner) (the deprecation message's replacement; TagOnly if no client needs the count) | Function removed (no declaration in 5.8); the backing ReplicatedLooseTags member is UE_DEPRECATED(5.7) at AbilitySystemComponent.h:1941 |
FGameplayAbilitySpec::DynamicAbilityTags | GetDynamicSpecSourceTags() | UE_DEPRECATED(5.5) in GameplayAbilitySpec.h:242 |
UAbilitySystemBlueprintLibrary::MakeSpecHandle | MakeSpecHandleByClass | UE_DEPRECATED(5.5) in AbilitySystemBlueprintLibrary.h:249 |
UAbilitySystemGlobals config members | GetDefault<UGameplayAbilitiesDeveloperSettings>() | UE_DEPRECATED(5.5) throughout AbilitySystemGlobals.h |
FGameplayEffectSpec::GetModifierMagnitude(ModifierIdx, bFactorInStackCount) | GetModifierMagnitude(int32 ModifierIdx) | UE_DEPRECATED(5.6) in GameplayEffect.h:1153 |
FActiveGameplayEffectHandle(int32), ResetGlobalHandleMap(), RemoveFromGlobalMap() | FActiveGameplayEffectHandle::GenerateNewHandle() or GetInstantExecutedHandle(); the global map is gone | UE_DEPRECATED(5.8) in ActiveGameplayEffectHandle.h:30,66,69 |
Common Mistakes
Implementing IAbilitySystemInterface only on the pawn: when the ASC lives on the PlayerState, the PlayerState must implement the interface too, otherwise UAbilitySystemBlueprintLibrary::GetAbilitySystemComponent fails on the owner.
Calling InitAbilityActorInfo only on the server: clients need it as well. Server path is PossessedBy, client path is OnRep_PlayerState. Without the client call, attribute change delegates never fire on the owning client.
Applying GEs before init: granting abilities or applying effects before InitAbilityActorInfo runs leaves the ASC without actor info and the attribute sets unregistered.
Clamping in the wrong hook: PreAttributeChange fires on every aggregator recompute, so it may only clamp NewValue. Death, hit reactions and gameplay events belong in PostGameplayEffectExecute, which only runs for executions (instant GEs and periodic ticks).
Forgetting CommitAbility: the ability runs, but no cost is paid and no cooldown starts.
Assuming loose tags replicate: AddLooseGameplayTag(Tag) defaults to EGameplayTagReplicationState::None. Pass TagOnly or CountToOwner from the server, or grant the tag through a GE.
Stacks silently capped: applications beyond GetStackLimitCount() are rejected without an error. Check GetCurrentStackCount(Handle) before assuming a stack landed.
Startup effects in BeginPlay without an authority check: late joiners re-apply them. Gate every GiveAbility and startup GE behind HasAuthority().
AI with no PlayerState: put the ASC on the AI character, call InitAbilityActorInfo(this, this) and set Minimal replication.
Related Skills
ue-gameplay-tags-messaging— tag definition (native tag macros, ini tag sources), containers,FGameplayTagQueryand gameplay messagingue-networking-replication—DOREPLIFETIMEvariants, RPCs, prediction keys, push modelue-animation-system— montage assets, notifies and slots that the montage ability tasks driveue-character-movement— movement modes that root-motion ability tasks manipulateue-cpp-foundations—UPROPERTY/UFUNCTIONspecifiers, delegates,TSubclassOf, subsystemsue-data-assets-tables—UCurveTableandUDataTableassets behind attribute initialisation andFScalableFloatue-state-trees— running abilities from State Tree tasksue-actor-component-architecture— component creation, subobject registration, replication of subobjectsue-gameplay-framework— PlayerState and Pawn lifecycle, and damage without GAS (TakeDamage,UDamageType)ue-input-system— Enhanced Input actions bound to ability input idsue-game-features— granting abilities and attribute sets from a game feature pluginue-niagara-effects— Niagara systems, user parameters, data interfaces and data channelsue-ui-umg-slate— UMG widgets, Slate, Common UI and MVVM
FAQ
What does the ue-gameplay-abilities skill do?
Use when implementing or debugging the Gameplay Ability System in C++ — abilities, effects, attributes, cues and the AbilitySystemComponent. Also use when the user mentions 'GAS', 'UGameplayAbility', 'ActivateAbility', 'CommitAbility', 'UGameplayEffect', 'UAttributeSet', 'FGameplayAttributeData', 'AbilitySystemComponent', 'InitAbilityActorInfo', 'GiveAbility', 'TryActivateAbility', 'ability task', 'GameplayCue', 'cooldown', 'cost', 'buff', 'debuff', 'damage execution' or 'ASC on PlayerState'. For montage playback, see ue-animation-system; for replication modes and prediction, see ue-networking-replication.
How do I install ue-gameplay-abilities?
Run npx skills add https://github.com/quodsoler/unreal-engine-skills --skill ue-gameplay-abilities in your project. The skills CLI detects the agents you use and copies the skill into the right folder. For Claude Code you can also place the skill folder at ~/.claude/skills/ue-gameplay-abilities/ (personal) or .claude/skills/ue-gameplay-abilities/ (project).
Which AI agents can use ue-gameplay-abilities?
Any agent that supports the open Agent Skills format (a folder with a SKILL.md file), including Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, Windsurf, Cline, OpenCode and more.
Is ue-gameplay-abilities safe to install?
No partner security audit is available yet. Skills can run commands and scripts, so read the SKILL.md and any bundled files before installing.
Who maintains ue-gameplay-abilities?
It is published by quodsoler in quodsoler/unreal-engine-skills. It has 1,157 recorded installs.
More from quodsoler/unreal-engine-skills
ue-cpp-foundations
quodsoler/unreal-engine-skills
Use when writing Unreal Engine C++ that touches the reflection system or core types: UCLASS, UPROPERTY, UFUNCTION, USTRUCT, UENUM, GENERATEDBODY, TObjectPtr, TWeakObjectPtr, TSharedPtr, FGCObject, TArray, TMap, TSet, TOptional, TVariant, DECLAREDYNAMICMULTICASTDELEGATE, AddDynamic, FName, FString, FText, UGameInstanceSubsystem, UWorldSubsystem, GetDefault, TNotNull. Also use when the user mentions 'UE C++', 'garbage collection', 'CDO', 'smart pointers' or 'specifiers'. For Actor and component lifecycle, see ue-actor-component-architecture; for Build.cs and modules, see ue-module-build-system; for Blueprint-facing functions and latent actions, see ue-blueprint-cpp-interop.
ue-ui-umg-slate
quodsoler/unreal-engine-skills
Use when writing or fixing Unreal Engine UI in C++ — UMG user widgets, Slate widgets, Common UI screens, or MVVM view models. Also use when the user mentions 'UUserWidget', 'NativeConstruct', 'BindWidget', 'CreateWidget', 'AddToViewport', 'ESlateVisibility', 'OnClicked', 'UListView', 'widget animation', 'SNew', 'SLATEBEGINARGS', 'SCompoundWidget', 'UCommonActivatableWidget', 'activatable widget stack', 'UCommonButtonBase', 'gamepad focus', 'FUIInputConfig', 'UMVVMViewModelBase', 'FieldNotify', or 'WidgetComponent'. For input modes and Enhanced Input, see ue-input-system; for Slate in editor tooling, see ue-editor-tools.
ue-editor-tools
quodsoler/unreal-engine-skills
Use when extending the Unreal Editor from C++ with detail customizations, editor utility widgets, menus, editor modes, asset definitions or editor subsystems. Also use when the user mentions 'IDetailCustomization', 'IPropertyTypeCustomization', 'CustomizeDetails', 'RegisterCustomClassLayout', 'IDetailLayoutBuilder', 'AddCustomRow', 'IPropertyHandle', 'UToolMenus', 'ExtendMenu', 'FToolMenuEntry', 'UEditorUtilityWidget', 'Blutility', 'UAssetActionUtility', 'UEditorSubsystem', 'UEdMode', 'UAssetDefinition', 'UFactory', 'FScopedTransaction', or 'editor module'. For Slate fundamentals, see ue-ui-umg-slate; for Build.cs wiring, see ue-module-build-system.
ue-project-context
quodsoler/unreal-engine-skills
Use when creating, refreshing or repairing .agents/ue-project-context.md, the project document every other UE skill reads first. Also use when the user says 'project context', 'set up context', 'UE context', 'scan my project', 'onboard the agent to my project', 'update project context', 'configure project', 'what engine version is this project on', 'which plugins do we have enabled', or complains that UE advice keeps coming out generic. For Build.cs and Target.cs mechanics, see ue-module-build-system; for naming and API-macro conventions, see ue-cpp-foundations; for GAS specifics, see ue-gameplay-abilities.
ue-testing-debugging
quodsoler/unreal-engine-skills
Use when writing or running Unreal Engine tests, adding logging, or profiling a build. Also use when the user mentions 'UELOG', 'log category', 'DEFINELOGCATEGORY', 'UELOGFMT', 'verbosity', 'check', 'ensure', 'ensureMsgf', 'verify', 'IMPLEMENTSIMPLEAUTOMATIONTEST', 'automation test', 'TESTCLASS', 'CQTest', 'AFunctionalTest', 'latent command', 'Unreal Insights', 'TRACECPUPROFILEREVENTSCOPE', 'TRACEBOOKMARK', 'stat unit', 'SCOPECYCLECOUNTER', 'memreport', 'DrawDebugLine', 'UEVLOG', 'gameplay debugger', 'ShowDebug', 'console command', 'CVar', or 'why is my frame time bad'. For module and target wiring, see ue-module-build-system; for editor tooling, see ue-editor-tools.
ue-module-build-system
quodsoler/unreal-engine-skills
Use when writing or fixing Build.cs, Target.cs, .uproject or .uplugin files, creating a module or plugin, or resolving an Unreal build error. Also use when the user mentions 'unresolved external symbol', 'LNK2019', 'cannot open include file', 'C1083', 'MODULENAMEAPI', 'PublicDependencyModuleNames', 'IWYU', 'PCHUsage', 'IMPLEMENTMODULE', 'IMPLEMENTPRIMARYGAMEMODULE', 'LoadingPhase', 'circular dependency', 'Missing precompiled manifest', 'EngineAssociation', 'IncludeOrderVersion', 'Live Coding'. For UCLASS/UPROPERTY rules see ue-cpp-foundations; for editor modules see ue-editor-tools; for Game Feature plugins see ue-game-features.
Popular frontend & design skills
setup-matt-pocock-skills
mattpocock/skills
Configure this repo for the engineering skills: set up its issue tracker, triage label vocabulary, and domain doc layout. Run once before first use of the other engineering skills.
frontend-design
anthropics/skills
Guidance for distinctive, intentional visual design when building new UI or reshaping an existing one. Helps with aesthetic direction, typography, and making choices that don't read as templated defaults.
hyperframes-animation
heygen-com/hyperframes
All animation knowledge for HyperFrames — atomic motion rules, multi-phase scene blueprints, scene transitions, broader motion-design techniques, AND the seven runtime adapters (GSAP default, plus Lottie, Three.js, Anime.js, CSS keyframes, Web Animations API, TypeGPU). Use for any motion or animation task: pick 2-4 rules and compose, or load a blueprint, or look up runtime-specific API (e.g. GSAP eases / Lottie player / Three.js mixer). Also covers auditing an existing composition's choreography (animation map) and 24 named text-animation effects. HyperFrames-native: single paused timeline, seek-safe, deterministic.
prototype
mattpocock/skills
Build a throwaway prototype to answer a design question. Use when the user wants to sanity-check whether a state model or logic feels right, or explore what a UI should look like.
hyperframes-core
heygen-com/hyperframes
The HyperFrames composition contract — build one renderable project. Use for composition structure, the data- timing attributes, class="clip", tracks, sub-compositions, variables, framework-owned media playback, deterministic-render rules, and validation. Read before writing composition HTML.
vercel-react-best-practices
vercel-labs/agent-skills
React and Next.js performance optimization guidelines from Vercel Engineering. This skill should be used when writing, reviewing, or refactoring React/Next.js code to ensure optimal performance patterns. Triggers on tasks involving React components, Next.js pages, data fetching, bundle optimization, or performance improvements.