mirror of
https://github.com/Donchitos/Claude-Code-Game-Studios.git
synced 2026-10-16 01:37:05 +00:00
Fix release for 1.1.2: the 14 longest skills keep their later phases after a compaction, a question nobody answered is never taken as an answer, settings read the same from a subfolder, the commit check works for a project in a subfolder of a larger repository, every skill opens with a title, and the shipped allow rules no longer approve deleting a branch or writing files without asking. Details in CHANGELOG.md; upgrade steps in UPGRADING.md (v1.1.2 → v1.1.3). Refs #83 Refs #133 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0185en4t76fPn7315q4c3nko
12 KiB
12 KiB
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
#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)
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
#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
#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 likeHealth = Clamp(Health, 0, MaxHealth)— itsNewValueis mutable.PreAttributeBaseChange()is called just before a change to an attribute's base value when an aggregator exists, andPostGameplayEffectExecute()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
#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(); the change is believed to have landed
// around 5.5.
// NOT SOURCEABLE — the 5.7 tag API for abilities is not covered by
// docs/engine-reference/unreal/ (no 5.7 API dump). Verify against the UE
// 5.7 docs before using this snippet, and correct both occurrences (here
// and in "Use Tags in Abilities") 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
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
// 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)
// 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
// 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
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
// In Ability Blueprint or C++:
// Create Gameplay Effect with Duration = Cooldown time
// Assign to Ability > Cooldown Gameplay Effect Class
Add Cost (Mana)
// Create Gameplay Effect that reduces Mana
// Assign to Ability > Cost Gameplay Effect Class
Common Patterns
Get Current Attribute Value
float CurrentHealth = AbilitySystemComponent->GetNumericAttribute(UMyAttributeSet::GetHealthAttribute());
Listen for Attribute Changes
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 ;
UAttributeSetAPI https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Plugins/GameplayAbilities/UAttributeSet ;PreAttributeChangehttps://dev.epicgames.com/documentation/en-us/unreal-engine/API/Plugins/GameplayAbilities/UAttributeSet/PreAttributeChange - https://github.com/tranek/GASDocumentation (community guide)