Files
Claude-Code-Game-Studios/docs/engine-reference/unreal/plugins/gameplay-ability-system.md
T
DonchitosandClaude Opus 5.5 b21fa0f7f2 Release 1.1.2 — the default path works end to end
Fix release for 1.1.1: the minimal path end to end, engine commands that
run on Godot, Unity and Unreal, hook warnings you can see, and verdicts
that say when they could not check. Details in CHANGELOG.md; upgrade
steps in UPGRADING.md (v1.1.1 → v1.1.2).

Fixes #67
Fixes #131

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WuJn2FdynEybfL5KC697nJ
2026-09-29 21:32:19 +10:00

411 lines
12 KiB
Markdown

# Unreal Engine 5.7 — Gameplay Ability System (GAS)
**Last verified:** 2026-02-13
**Status:** Production-Ready
**Plugin:** `GameplayAbilities` (built-in, enable in Plugins)
---
## Overview
**Gameplay Ability System (GAS)** is a modular framework for building abilities, attributes,
effects, and gameplay mechanics. It's the standard for RPGs, MOBAs, shooters with abilities,
and any game with complex ability systems.
**Use GAS for:**
- Character abilities (spells, skills, attacks)
- Attributes (health, mana, stamina, stats)
- Buffs/debuffs (temporary effects)
- Cooldowns and costs
- Damage calculation
- Multiplayer-ready ability replication
---
## Core Concepts
### 1. **Ability System Component** (ASC)
- The main component that owns abilities, attributes, and effects
- Added to Characters or PlayerStates
### 2. **Gameplay Abilities**
- Individual skills/actions (fireball, heal, dash, etc.)
- Activated, committed (cost/cooldown), and can be cancelled
### 3. **Attributes & Attribute Sets**
- Stats that can be modified (Health, Mana, Stamina, Strength, etc.)
- Stored in Attribute Sets
### 4. **Gameplay Effects**
- Modify attributes (damage, healing, buffs, debuffs)
- Can be instant, duration-based, or infinite
### 5. **Gameplay Tags**
- Hierarchical tags for ability logic (e.g., `Ability.Attack.Melee`, `Status.Stunned`)
---
## Setup
### 1. Enable Plugin
`Edit > Plugins > Gameplay Abilities > Enabled > Restart`
### 2. Add Ability System Component
```cpp
#include "AbilitySystemComponent.h"
#include "AttributeSet.h"
UCLASS()
class AMyCharacter : public ACharacter {
GENERATED_BODY()
public:
AMyCharacter() {
// Create ASC
AbilitySystemComponent = CreateDefaultSubobject<UAbilitySystemComponent>(TEXT("AbilitySystem"));
AbilitySystemComponent->SetIsReplicated(true);
AbilitySystemComponent->SetReplicationMode(EGameplayEffectReplicationMode::Mixed);
// Create Attribute Set
AttributeSet = CreateDefaultSubobject<UMyAttributeSet>(TEXT("AttributeSet"));
}
protected:
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Abilities")
TObjectPtr<UAbilitySystemComponent> AbilitySystemComponent;
UPROPERTY()
TObjectPtr<const UAttributeSet> AttributeSet;
};
```
### 3. Initialize ASC (Important for Multiplayer)
```cpp
void AMyCharacter::PossessedBy(AController* NewController) {
Super::PossessedBy(NewController);
// Server: Initialize ASC
if (AbilitySystemComponent) {
AbilitySystemComponent->InitAbilityActorInfo(this, this);
GiveDefaultAbilities();
}
}
void AMyCharacter::OnRep_PlayerState() {
Super::OnRep_PlayerState();
// Client: Initialize ASC
if (AbilitySystemComponent) {
AbilitySystemComponent->InitAbilityActorInfo(this, this);
}
}
```
---
## Attributes & Attribute Sets
### Create Attribute Set
```cpp
#include "AttributeSet.h"
#include "AbilitySystemComponent.h"
UCLASS()
class UMyAttributeSet : public UAttributeSet {
GENERATED_BODY()
public:
UMyAttributeSet();
// Health
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)
// Mana
UPROPERTY(BlueprintReadOnly, Category = "Attributes", ReplicatedUsing = OnRep_Mana)
FGameplayAttributeData Mana;
ATTRIBUTE_ACCESSORS(UMyAttributeSet, Mana)
virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;
protected:
UFUNCTION()
virtual void OnRep_Health(const FGameplayAttributeData& OldHealth);
UFUNCTION()
virtual void OnRep_MaxHealth(const FGameplayAttributeData& OldMaxHealth);
UFUNCTION()
virtual void OnRep_Mana(const FGameplayAttributeData& OldMana);
};
```
### Implement Attribute Set
```cpp
#include "Net/UnrealNetwork.h"
UMyAttributeSet::UMyAttributeSet() {
// Default values
Health = 100.0f;
MaxHealth = 100.0f;
Mana = 50.0f;
}
void UMyAttributeSet::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const {
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
DOREPLIFETIME_CONDITION_NOTIFY(UMyAttributeSet, Health, COND_None, REPNOTIFY_Always);
DOREPLIFETIME_CONDITION_NOTIFY(UMyAttributeSet, MaxHealth, COND_None, REPNOTIFY_Always);
DOREPLIFETIME_CONDITION_NOTIFY(UMyAttributeSet, Mana, COND_None, REPNOTIFY_Always);
}
void UMyAttributeSet::OnRep_Health(const FGameplayAttributeData& OldHealth) {
GAMEPLAYATTRIBUTE_REPNOTIFY(UMyAttributeSet, Health, OldHealth);
}
// Implement other OnRep functions similarly...
```
### Clamping Attributes
Attribute Sets have no built-in clamping: the Data Table `Min Value` and
`Max Value` columns have no effect. Clamp in the Attribute Set:
- `PreAttributeChange()` is called just before any modification to an
attribute, and is the hook for rules like
`Health = Clamp(Health, 0, MaxHealth)` — its `NewValue` is mutable.
- `PreAttributeBaseChange()` is called just before a change to an attribute's
**base** value when an aggregator exists, and `PostGameplayEffectExecute()`
just after a Gameplay Effect is executed to modify the base value — clamp
base-value changes from instant effects there.
Stacking rules govern re-applications of the same Gameplay Effect; they do not
bound one attribute pushed by different effects.
---
## Gameplay Abilities
### Create Gameplay Ability
```cpp
#include "Abilities/GameplayAbility.h"
UCLASS()
class UGA_Fireball : public UGameplayAbility {
GENERATED_BODY()
public:
UGA_Fireball() {
// Ability config
InstancingPolicy = EGameplayAbilityInstancingPolicy::InstancedPerActor;
NetExecutionPolicy = EGameplayAbilityNetExecutionPolicy::ServerInitiated;
// Tags
// ⚠️ UNVERIFIED FOR 5.7 — `AbilityTags` may be deprecated in favour of
// SetAssetTags()/GetAssetTags(). Reported by the `unreal-specialist`
// agent (2026-08-12), which believed the change landed around 5.5 and
// correctly REFUSED to emit code on a symbol it could not verify.
// NOT SOURCEABLE offline: this repo has no 5.7 API dump to check against,
// and the same knowledge-gap warning that governs the agent governs this
// file. Verify against the UE 5.7 docs before using this snippet, and
// correct both occurrences (here and ~line 328) together.
AbilityTags.AddTag(FGameplayTag::RequestGameplayTag(FName("Ability.Attack.Fireball")));
}
virtual void ActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo,
const FGameplayAbilityActivationInfo ActivationInfo, const FGameplayEventData* TriggerEventData) override {
if (!CommitAbility(Handle, ActorInfo, ActivationInfo)) {
// Failed to commit (not enough mana, on cooldown, etc.)
EndAbility(Handle, ActorInfo, ActivationInfo, true, true);
return;
}
// Spawn fireball projectile
SpawnFireball();
// End ability
EndAbility(Handle, ActorInfo, ActivationInfo, true, false);
}
void SpawnFireball() {
// Spawn fireball logic
}
};
```
### Grant Abilities to Character
```cpp
void AMyCharacter::GiveDefaultAbilities() {
if (!HasAuthority() || !AbilitySystemComponent) return;
// Grant abilities
AbilitySystemComponent->GiveAbility(FGameplayAbilitySpec(UGA_Fireball::StaticClass(), 1, INDEX_NONE, this));
AbilitySystemComponent->GiveAbility(FGameplayAbilitySpec(UGA_Heal::StaticClass(), 1, INDEX_NONE, this));
}
```
### Activate Ability
```cpp
// Activate by class
AbilitySystemComponent->TryActivateAbilityByClass(UGA_Fireball::StaticClass());
// Activate by tag
FGameplayTagContainer TagContainer;
TagContainer.AddTag(FGameplayTag::RequestGameplayTag(FName("Ability.Attack.Fireball")));
AbilitySystemComponent->TryActivateAbilitiesByTag(TagContainer);
```
---
## Gameplay Effects
### Create Gameplay Effect (Damage)
```cpp
// Create Blueprint: Content Browser > Gameplay > Gameplay Effect
// OR in C++:
UCLASS()
class UGE_Damage : public UGameplayEffect {
GENERATED_BODY()
public:
UGE_Damage() {
// Instant damage
DurationPolicy = EGameplayEffectDurationType::Instant;
// Modifier: Reduce Health
FGameplayModifierInfo ModifierInfo;
ModifierInfo.Attribute = UMyAttributeSet::GetHealthAttribute();
ModifierInfo.ModifierOp = EGameplayModOp::Additive;
ModifierInfo.ModifierMagnitude = FScalableFloat(-25.0f); // -25 health
Modifiers.Add(ModifierInfo);
}
};
```
### Apply Gameplay Effect
```cpp
// Apply damage to target
if (UAbilitySystemComponent* TargetASC = UAbilitySystemBlueprintLibrary::GetAbilitySystemComponent(Target)) {
FGameplayEffectContextHandle EffectContext = AbilitySystemComponent->MakeEffectContext();
EffectContext.AddSourceObject(this);
FGameplayEffectSpecHandle SpecHandle = AbilitySystemComponent->MakeOutgoingSpec(
UGE_Damage::StaticClass(), 1, EffectContext);
if (SpecHandle.IsValid()) {
AbilitySystemComponent->ApplyGameplayEffectSpecToTarget(*SpecHandle.Data.Get(), TargetASC);
}
}
```
---
## Gameplay Tags
### Define Tags
`Project Settings > Project > Gameplay Tags > Gameplay Tag List`
Example hierarchy:
```
Ability
├─ Ability.Attack
│ ├─ Ability.Attack.Melee
│ └─ Ability.Attack.Ranged
├─ Ability.Defend
└─ Ability.Utility
Status
├─ Status.Stunned
├─ Status.Invulnerable
└─ Status.Silenced
```
### Use Tags in Abilities
```cpp
UCLASS()
class UGA_MeleeAttack : public UGameplayAbility {
GENERATED_BODY()
public:
UGA_MeleeAttack() {
// This ability has these tags
AbilityTags.AddTag(FGameplayTag::RequestGameplayTag(FName("Ability.Attack.Melee")));
// Block these tags while active
BlockAbilitiesWithTag.AddTag(FGameplayTag::RequestGameplayTag(FName("Ability.Attack")));
// Cancel these abilities when activated
CancelAbilitiesWithTag.AddTag(FGameplayTag::RequestGameplayTag(FName("Ability.Defend")));
// Can't activate if target has these tags
ActivationBlockedTags.AddTag(FGameplayTag::RequestGameplayTag(FName("Status.Stunned")));
}
};
```
---
## Cooldowns & Costs
### Add Cooldown
```cpp
// In Ability Blueprint or C++:
// Create Gameplay Effect with Duration = Cooldown time
// Assign to Ability > Cooldown Gameplay Effect Class
```
### Add Cost (Mana)
```cpp
// Create Gameplay Effect that reduces Mana
// Assign to Ability > Cost Gameplay Effect Class
```
---
## Common Patterns
### Get Current Attribute Value
```cpp
float CurrentHealth = AbilitySystemComponent->GetNumericAttribute(UMyAttributeSet::GetHealthAttribute());
```
### Listen for Attribute Changes
```cpp
AbilitySystemComponent->GetGameplayAttributeValueChangeDelegate(UMyAttributeSet::GetHealthAttribute())
.AddUObject(this, &AMyCharacter::OnHealthChanged);
void AMyCharacter::OnHealthChanged(const FOnAttributeChangeData& Data) {
UE_LOG(LogTemp, Warning, TEXT("Health: %f"), Data.NewValue);
}
```
---
## Sources
- https://docs.unrealengine.com/5.7/en-US/gameplay-ability-system-for-unreal-engine/
- Clamping: *Gameplay Attributes and Attribute Sets* https://dev.epicgames.com/documentation/en-us/unreal-engine/gameplay-attributes-and-attribute-sets-for-the-gameplay-ability-system-in-unreal-engine ; `UAttributeSet` API https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Plugins/GameplayAbilities/UAttributeSet ; `PreAttributeChange` https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Plugins/GameplayAbilities/UAttributeSet/PreAttributeChange
- https://github.com/tranek/GASDocumentation (community guide)