Loading...
Loading...
Use this skill when working with GAS, Gameplay Ability System, GameplayAbility, GameplayEffect, AttributeSet, GameplayTags, ability system, buffs, debuffs, cooldowns, or attribute modification. See references/ for detailed setup patterns, effect configuration, and ability task usage.
npx skill4agent add quodsoler/unreal-engine-skills ue-gameplay-abilities.agents/ue-project-context.mdUAbilitySystemComponent| Pillar | Class | Purpose |
|---|---|---|
| Abilities | | Logic for what happens when activated |
| Effects | | Data-driven stat mutations (instant, duration, infinite) |
| Attributes | | Float properties representing character stats |
GameplayAbilities.uproject[ProjectName].Build.csPublicDependencyModuleNames.AddRange(new string[]
{
"GameplayAbilities", "GameplayTags", "GameplayTasks"
});references/gas-setup-patterns.mdIAbilitySystemInterface#include "AbilitySystemInterface.h"
UCLASS()
class AMyCharacter : public ACharacter, public IAbilitySystemInterface
{
GENERATED_BODY()
public:
virtual UAbilitySystemComponent* GetAbilitySystemComponent() const override
{ return AbilitySystemComponent; }
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "GAS")
TObjectPtr<UAbilitySystemComponent> AbilitySystemComponent;
};// In BeginPlay or PossessedBy on the server:
AbilitySystemComponent->SetReplicationMode(EGameplayEffectReplicationMode::Mixed);| Mode | When to Use |
|---|---|
| AI or non-player actors; no GE replication to simulated proxies |
| Player-controlled characters (owner gets full info, others get minimal) |
| Non-player games or debugging; all GEs replicate to all clients |
PossessedByOnRep_PlayerStateASC->InitAbilityActorInfo(OwnerActor, AvatarActor)references/gas-setup-patterns.md#include "Abilities/GameplayAbility.h"
UCLASS()
class UMyFireballAbility : public UGameplayAbility
{
GENERATED_BODY()
public:
UMyFireballAbility();
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;
// Ability Tasks — async building blocks for latent abilities:
// UAbilityTask_WaitTargetData — waits for targeting (crosshair/AoE confirm)
// UAbilityTask_WaitGameplayEvent — waits for a GameplayEvent tag (e.g., anim notify)
// UAbilityTask_WaitDelay — simple timer
// UAbilityTask_PlayMontageAndWait — montage with callbacks (see ue-animation-system)
// See references/ability-task-reference.md for full list and custom task pattern.
// CancelAbility — called by CancelAbilitiesWithTag or ASC->CancelAbility(Handle)
// Internally calls EndAbility with bWasCancelled=true. Override to add cleanup:
virtual void CancelAbility(const FGameplayAbilitySpecHandle Handle,
const FGameplayAbilityActorInfo* ActorInfo,
const FGameplayAbilityActivationInfo ActivationInfo,
bool bReplicateCancelAbility) override;
// Custom activation guard — return false to block activation beyond tag checks
virtual bool CanActivateAbility(const FGameplayAbilitySpecHandle Handle,
const FGameplayAbilityActorInfo* ActorInfo, /*...*/) const override;
// Must call Super first. Add custom checks (resource availability, cooldown state).
protected:
UPROPERTY(EditDefaultsOnly, Category = "GAS")
TSubclassOf<UGameplayEffect> DamageEffect;
};void UMyFireballAbility::ActivateAbility(const FGameplayAbilitySpecHandle Handle,
const FGameplayAbilityActorInfo* ActorInfo,
const FGameplayAbilityActivationInfo ActivationInfo,
const FGameplayEventData* TriggerEventData)
{
// 1. Commit: validates and applies cost + cooldown
if (!CommitAbility(Handle, ActorInfo, ActivationInfo))
{
EndAbility(Handle, ActorInfo, ActivationInfo, true, true);
return;
}
// 2. Apply effect / spawn projectile / etc.
FGameplayEffectSpecHandle Spec = MakeOutgoingGameplayEffectSpec(DamageEffect, GetAbilityLevel());
FGameplayAbilityTargetDataHandle TargetData =
UAbilitySystemBlueprintLibrary::AbilityTargetDataFromActor(
ActorInfo->AvatarActor.Get());
ApplyGameplayEffectSpecToTarget(Handle, ActorInfo, ActivationInfo, Spec, TargetData);
// 3. End (instant abilities end immediately; latent abilities wait for tasks)
EndAbility(Handle, ActorInfo, ActivationInfo, true, false);
}CommitAbilityCommitAbilityCostCommitAbilityCooldownUMyFireballAbility::UMyFireballAbility()
{
// InstancedPerActor - one instance per actor; cheapest for persistent abilities
// InstancedPerExecution - new instance each activation; safe for concurrency
// NonInstanced - CDO runs the ability; no per-execution state
InstancingPolicy = EGameplayAbilityInstancingPolicy::InstancedPerActor;
// LocalPredicted - client runs immediately, server validates (player abilities)
// ServerOnly - authority only, no prediction
// LocalOnly - local client only (UI, cosmetic)
// ServerInitiated - server activates, clients run non-authoritative predicted copy
NetExecutionPolicy = EGameplayAbilityNetExecutionPolicy::LocalPredicted;
}// Grant (server/authority only):
FGameplayAbilitySpecHandle Handle = ASC->GiveAbility(
FGameplayAbilitySpec(UMyFireballAbility::StaticClass(), 1 /*Level*/));
ASC->TryActivateAbility(Handle); // by handle
ASC->TryActivateAbilityByClass(UMyFireballAbility::StaticClass()); // by class
ASC->TryActivateAbilitiesByTag( // by tag
FGameplayTagContainer(FGameplayTag::RequestGameplayTag("Ability.Skill.Fireball")));// Tags this ability grants to its owner while active:
ActivationOwnedTags.AddTag(FGameplayTag::RequestGameplayTag("Ability.Active.Casting"));
// Tags that prevent this ability from activating:
ActivationBlockedTags.AddTag(FGameplayTag::RequestGameplayTag("State.Stunned"));
// Cancel other active abilities with these tags on activation:
CancelAbilitiesWithTag.AddTag(FGameplayTag::RequestGameplayTag("Ability.Active.Melee"));| Policy | Behavior |
|---|---|
| Executes once; modifies attribute base value permanently |
| Active for set duration; uses |
| Active until |
FGameplayEffectContextHandle Ctx = ASC->MakeEffectContext();
FGameplayEffectSpecHandle Spec = ASC->MakeOutgoingSpec(UMyDamageEffect::StaticClass(), Level, Ctx);
// SetByCaller: inject runtime magnitude using a tag key
Spec.Data->SetSetByCallerMagnitude(
FGameplayTag::RequestGameplayTag("SetByCaller.Damage"), 75.f);
ASC->ApplyGameplayEffectSpecToSelf(*Spec.Data.Get()); // self
ASC->ApplyGameplayEffectSpecToTarget(*Spec.Data.Get(), TargetASC); // target
ASC->RemoveActiveGameplayEffect(ActiveHandle); // by handle
ASC->RemoveActiveGameplayEffectBySourceEffect(
UMyDamageEffect::StaticClass(), nullptr); // by classreferences/gameplay-effect-reference.mdUGameplayEffectExecutionCalculation// MyHealthSet.h
#include "AttributeSet.h"
#include "AbilitySystemComponent.h"
// Convenience macro - define in your project headers
#define ATTRIBUTE_ACCESSORS(ClassName, PropertyName) \
GAMEPLAYATTRIBUTE_PROPERTY_GETTER(ClassName, PropertyName) \
GAMEPLAYATTRIBUTE_VALUE_GETTER(PropertyName) \
GAMEPLAYATTRIBUTE_VALUE_SETTER(PropertyName) \
GAMEPLAYATTRIBUTE_VALUE_INITTER(PropertyName)
UCLASS()
class UMyHealthSet : public UAttributeSet
{
GENERATED_BODY()
public:
UMyHealthSet();
// Called BEFORE any modification - use for clamping current value
virtual void PreAttributeChange(const FGameplayAttribute& Attribute, float& NewValue) override;
// Called AFTER instant GE executes - react to changes (death, events)
virtual void PostGameplayEffectExecute(const FGameplayEffectModCallbackData& Data) override;
virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;
UPROPERTY(BlueprintReadOnly, ReplicatedUsing = OnRep_Health, Category = "Health")
FGameplayAttributeData Health;
ATTRIBUTE_ACCESSORS(UMyHealthSet, Health)
UPROPERTY(BlueprintReadOnly, ReplicatedUsing = OnRep_MaxHealth, Category = "Health")
FGameplayAttributeData MaxHealth;
ATTRIBUTE_ACCESSORS(UMyHealthSet, MaxHealth)
protected:
UFUNCTION()
void OnRep_Health(const FGameplayAttributeData& OldHealth);
UFUNCTION()
void OnRep_MaxHealth(const FGameplayAttributeData& OldMaxHealth);
};.cppvoid UMyHealthSet::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
DOREPLIFETIME_CONDITION_NOTIFY(UMyHealthSet, Health, COND_None, REPNOTIFY_Always);
DOREPLIFETIME_CONDITION_NOTIFY(UMyHealthSet, MaxHealth, COND_None, REPNOTIFY_Always);
}
void UMyHealthSet::OnRep_Health(const FGameplayAttributeData& OldHealth)
{
GAMEPLAYATTRIBUTE_REPNOTIFY(UMyHealthSet, Health, OldHealth);
}
// PreAttributeChange: clamp CURRENT value before any modification
void UMyHealthSet::PreAttributeChange(const FGameplayAttribute& Attribute, float& NewValue)
{
Super::PreAttributeChange(Attribute, NewValue);
if (Attribute == GetHealthAttribute())
NewValue = FMath::Clamp(NewValue, 0.f, GetMaxHealth());
}
// PostGameplayEffectExecute: react AFTER instant GE modifies base value (damage, death)
void UMyHealthSet::PostGameplayEffectExecute(const FGameplayEffectModCallbackData& Data)
{
Super::PostGameplayEffectExecute(Data);
if (Data.EvaluatedData.Attribute == GetHealthAttribute())
{
SetHealth(FMath::Clamp(GetHealth(), 0.f, GetMaxHealth()));
if (GetHealth() <= 0.f) { /* trigger death */ }
}
}// In PlayerState or Character constructor:
// Option 1: CreateDefaultSubobject (auto-registered as subobject)
HealthSet = CreateDefaultSubobject<UMyHealthSet>(TEXT("HealthSet"));
// Option 2: Runtime (authority only) — create and register as subobject:
UMyHealthSet* NewSet = NewObject<UMyHealthSet>(this);
AbilitySystemComponent->AddSpawnedAttribute(NewSet);
// Read attribute value:
float CurrentHealth = AbilitySystemComponent->GetNumericAttribute(
UMyHealthSet::GetHealthAttribute());UAttributeSetUHealthSetUOffenseSetConfig/DefaultGameplayTags.ini// MyGameplayTags.h
#include "NativeGameplayTags.h"
UE_DECLARE_GAMEPLAY_TAG_EXTERN(TAG_Ability_Fireball)
UE_DECLARE_GAMEPLAY_TAG_EXTERN(TAG_State_Stunned)
// MyGameplayTags.cpp
UE_DEFINE_GAMEPLAY_TAG_COMMENT(TAG_Ability_Fireball, "Ability.Skill.Fireball", "Fireball ability")
UE_DEFINE_GAMEPLAY_TAG_COMMENT(TAG_State_Stunned, "State.Stunned", "Actor is stunned")"A.1".MatchesTag("A") == trueMatchesTagExactFGameplayTagContainer Tags;
Tags.HasTag(FireballTag); // parent-aware match
Tags.HasTagExact(FireballTag); // exact only
Tags.HasAny(OtherContainer);
Tags.HasAll(OtherContainer);
// Query ASC:
ASC->HasMatchingGameplayTag(TAG_State_Stunned);
ASC->GetOwnedGameplayTags(); // FGameplayTagContainer
// Listen for changes:
ASC->RegisterGameplayTagEvent(TAG_State_Stunned, EGameplayTagEventType::NewOrRemoved)
.AddUObject(this, &AMyCharacter::OnStunnedTagChanged);ASC->AddLooseGameplayTag(TAG_State_Stunned);
ASC->RemoveLooseGameplayTag(TAG_State_Stunned);
// Loose tags are NOT replicated by default. To replicate a loose tag,
// pass EGameplayTagReplicationState::TagOnly as the third argument:
ASC->AddLooseGameplayTag(TAG_State_Buffed, 1, EGameplayTagReplicationState::TagOnly);
ASC->RemoveLooseGameplayTag(TAG_State_Buffed, 1, EGameplayTagReplicationState::TagOnly);GameplayCue.FGameplayEffectCueGameplayCueTags// Burst (one-shot):
ASC->ExecuteGameplayCue(FGameplayTag::RequestGameplayTag("GameplayCue.Hit.Fire"),
ASC->MakeEffectContext());
// Persistent (add/remove pair):
ASC->AddGameplayCue(FGameplayTag::RequestGameplayTag("GameplayCue.Buff.Speed"));
ASC->RemoveGameplayCue(FGameplayTag::RequestGameplayTag("GameplayCue.Buff.Speed"));
// Poll active state:
bool bActive = ASC->IsGameplayCueActive(FGameplayTag::RequestGameplayTag("GameplayCue.Buff.Speed"));AGameplayCueNotify_ActorOnActiveWhileActiveOnRemoveAGameplayCueNotify_StaticOnExecute/Game/GAS/GameplayCues/UGameplayCueManagerIAbilitySystemInterfaceUAbilitySystemBlueprintLibraryOnRep_PlayerStatePossessedByPreAttributeChangePostGameplayEffectExecutePreAttributeChangeAddLooseGameplayTagEGameplayTagReplicationState::TagOnlyLimitCountGetCurrentStackCountInitAbilityActorInfo(AICharacter, AICharacter)MinimalFActiveGameplayEffectsContainerInitAbilityActorInfoBeginPlayreferences/gas-setup-patterns.mdreferences/gameplay-effect-reference.mdreferences/ability-task-reference.mdue-actor-component-architectureue-networking-replicationue-animation-systemue-gameplay-frameworkue-cpp-foundations