1169 字
6 分钟

UE5 Gameplay Ability System (GAS) 完全指南

深入解析Unreal Engines 5的Gameplay Ability System,从核心概念到实战应用,帮你快速掌握技能系统开发
2026-03-30
2026-03-30

前言#

Gameplay Ability System(GAS)是Epic官方推出的强大技能系统框架,被《堡垒之夜》等顶级游戏采用。它提供了一套完整的技能、buff、冷却管理的解决方案。

本文带你从零理解GAS的设计思想,并手把手实现一个简单的技能系统。


什么是GAS?#

GAS是Unreal Engine的核心技能/属性系统框架,核心特点是:

特性说明
ASC架构Ability System Component驱动
属性委托GameplayAttribute系统
技能标签Tag驱动的权限控制
预测系统客户端预测支持
技能委托完整的生命周期事件

简单来说:GAS让你能优雅地实现技能、buff、属性、冷却一套完整的战斗系统。


GAS核心概念#

1. ASC(Ability System Component)#

挂在Actor上的核心组件,负责管理所有技能:

UPROPERTY()
UAbilitySystemComponent* AbilitySystemComponent;

2. AttributeSet(属性集)#

存储角色的数值属性(生命值、魔法值、攻击力等):

UCLASS()
class UMyAttributeSet : public UAttributeSet
{
GENERATED_BODY()
public:
UPROPERTY()
float Health = 100.f;
UPROPERTY()
float MaxHealth = 100.f;
UPROPERTY()
float Mana = 50.f;
UPROPERTY()
float MaxMana = 50.f;
UPROPERTY()
float AttackPower = 10.f;
};

3. GameplayAbility(技能)#

具体的技能逻辑:

UCLASS()
class UMyGameplayAbility : public UGameplayAbility
{
GENERATED_BODY()
public:
// 技能激活时调用
virtual void ActivateAbility(const FGameplayAbilitySpecHandle Handle,
FGameplayAbilityActorInfo* ActorInfo,
const FGameplayAbilityActivationInfo& ActivationInfo,
FOnGameplayAbilityEnded::FDelegate* OnEnded) override;
// 技能结束时调用
virtual void EndAbility(const FGameplayAbilitySpecHandle Handle,
FGameplayAbilityActorInfo* ActorInfo,
FGameplayAbilityActivationInfo ActivationInfo,
bool bReplicateEndAbility,
bool bWasCancelled) override;
};

4. GameplayEffect(效果)#

用于修改属性(buff/debuff):

// 瞬间生效的效果(回血、掉血)
TSubclassOf<UGameplayEffect> InstantEffect;
// 持续效果(持续回血、dot)
TSubclassOf<UGameplayEffect> DurationEffect;
// 无限持续效果(buff)
TSubclassOf<UGameplayEffect> InfiniteEffect;

5. GameplayTags(标签)#

用于权限控制和技能识别:

Ability.Book.Fire
// 在ProjectSettings中定义Tag
// Ability.Book.Ice
// Buff.Shield
// Debuff.Slow

项目配置#

启用GAS插件#

Edit > Plugins 中启用:

  • GameplayAbilities — 核心GAS插件

创建AttributeSet#

MyAttributeSet.h
#pragma once
#include "CoreMinimal.h"
#include "AttributeSet.h"
#include "MyAttributeSet.generated.h"
UCLASS()
class UMyAttributeSet : public UAttributeSet
{
GENERATED_BODY()
public:
// 生命值
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Attributes")
FGameplayAttributeData Health;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Attributes")
FGameplayAttributeData MaxHealth;
// 魔法值
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Attributes")
FGameplayAttributeData Mana;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Attributes")
FGameplayAttributeData MaxMana;
// 攻击力
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Attributes")
FGameplayAttributeData AttackPower;
// 回调:当属性被修改时触发
virtual void PostGameplayEffectExecute(const FGameplayEffectModCallbackData& Data) override;
};
MyAttributeSet.cpp
#include "MyAttributeSet.h"
#include "GameplayEffect.h"
#include "GameplayEffectExtension.h"
void UMyAttributeSet::PostGameplayEffectExecute(const FGameplayEffectModCallbackData& Data)
{
if (Data.EvaluatedData.Attribute == GetHealthAttribute())
{
SetHealth(FMath::Clamp(GetHealth(), 0.f, GetMaxHealth()));
}
else if (Data.EvaluatedData.Attribute == GetManaAttribute())
{
SetMana(FMath::Clamp(GetMana(), 0.f, GetMaxMana()));
}
}

绑定ASC到Character#

MyCharacter.h
UCLASS()
class AMyCharacter : public ACharacter
{
GENERATED_BODY()
public:
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Abilities")
TObjectPtr<UAbilitySystemComponent> AbilitySystemComponent;
UPROPERTY()
TObjectPtr<UMyAttributeSet> AttributeSet;
virtual void PossessedBy(AController* NewController) override;
virtual void OnRep_PlayerState() override;
};
MyCharacter.cpp
#include "MyCharacter.h"
#include "MyAttributeSet.h"
void AMyCharacter::PossessedBy(AController* NewController)
{
Super::PossessedBy(NewController);
if (AbilitySystemComponent)
{
AbilitySystemComponent->InitAbilityActorInfo(this, this);
// 给ASC注册AttributeSet
AbilitySystemComponent->AddAttributeSetSubobject(AttributeSet);
// 赋予初始技能
GiveDefaultAbilities();
}
}
void AMyCharacter::OnRep_PlayerState()
{
Super::OnRep_PlayerState();
if (AbilitySystemComponent)
{
AbilitySystemComponent->InitAbilityActorInfo(this, this);
}
}
void AMyCharacter::GiveDefaultAbilities()
{
// 在这里赋予角色的默认技能
// 使用GrantAbility或通过DataAsset配置
}

实战:创建Fireball技能#

步骤1:创建技能蓝图#

  1. 创建GameplayAbility子类蓝图 BP_FireballAbility
  2. 在蓝图编辑器中设置:
    • Ability Tags:添加 Damage.Fire
    • Cooldown:设置冷却时间
    • Cost:设置消耗(魔法值)

步骤2:实现技能逻辑#

FireballAbility.h
UCLASS()
class UFireballAbility : public UGameplayAbility
{
GENERATED_BODY()
public:
// 发射火球
virtual void ActivateAbility(const FGameplayAbilitySpecHandle Handle,
FGameplayAbilityActorInfo* ActorInfo,
const FGameplayAbilityActivationInfo& ActivationInfo,
FOnGameplayAbilityEnded::FDelegate* OnEnded) override;
// 激活技能的输入事件
UFUNCTION(BlueprintCallable, Category = "Ability")
void InputPressed(const FGameplayAbilitySpecHandle Handle,
const FGameplayAbilityActorInfo* ActorInfo,
const FGameplayAbilityActivationInfo& ActivationInfo);
};
FireballAbility.cpp
#include "FireballAbility.h"
#include "Abilities/GameplayAbilityTargetActor_SingleLineTrace.h"
#include "Abilities/GameplayAbilityTypes.h"
void UFireballAbility::ActivateAbility(const FGameplayAbilitySpecHandle Handle,
FGameplayAbilityActorInfo* ActorInfo,
const FGameplayAbilityActivationInfo& ActivationInfo,
FOnGameplayAbilityEnded::FDelegate* OnEnded)
{
// 检查技能是否有效
if (!CommitAbility(Handle, ActorInfo, ActivationInfo))
{
EndAbility(Handle, ActorInfo, ActivationInfo, true, false);
return;
}
// 获取技能所有者
AActor* Owner = ActorInfo->OwnerActor.Get();
// 生成火球逻辑...
// 这里可以Spawn一个Actor或播放特效
UE_LOG(LogTemp, Warning, TEXT("Fireball Activated!"));
// 结束技能
EndAbility(Handle, ActorInfo, ActivationInfo, false, false);
}
void UFireballAbility::InputPressed(const FGameplayAbilitySpecHandle Handle,
const FGameplayAbilityActorInfo* ActorInfo,
const FGameplayAbilityActivationInfo& ActivationInfo)
{
TryActivateAbility(Handle);
}

步骤3:赋予技能#

// 在Character的GiveDefaultAbilities中
void AMyCharacter::GiveDefaultAbilities()
{
if (!AbilitySystemComponent) return;
// 创建技能Spec
FGameplayAbilitySpec Spec;
Spec.Ability = NewObject<UFireballAbility>();
Spec.Level = 1;
// 赋予技能
AbilitySystemComponent->GiveAbility(Spec);
}

冷却系统#

设置Cooldown GameplayEffect#

// 定义冷却GE
TSubclassOf<UGameplayEffect> CooldownGE = StaticLoadClass(
UGameplayEffect::StaticClass(),
nullptr,
TEXT("GameplayEffect'/Game/Effects/GE_Cooldown.GE_Cooldown_C'")
);
// 检查是否在冷却中
bool AMyCharacter::IsAbilityOnCooldown(FGameplayTag AbilityTag)
{
FGameplayTagContainer OwnedTags;
AbilitySystemComponent->GetOwnedGameplayTags(OwnedTags);
return OwnedTags.HasTag(AbilityTag);
}

常见问题#

Q: GAS和普通函数调用的区别?#

A: GAS提供了完整的生命周期管理、预测系统、网络同步、冷却/消耗验证。普通函数调用没有这些。

Q: AttributeSet为什么要用FGameplayAttributeData而不是float?#

A: FGameplayAttributeData支持元属性(MaxHealth)和Clamp设置,能正确处理属性比例修改。

Q: 如何调试GAS?#

A: 使用ASC->Debug命令可以在屏幕上显示所有技能和属性的详细信息。


总结#

GAS是UE5最强大的技能系统框架,核心组成:

  1. ASC — 技能系统核心组件
  2. AttributeSet — 管理角色属性
  3. GameplayAbility — 定义技能逻辑
  4. GameplayEffect — 实现buff/debuff
  5. GameplayTags — 权限控制和识别

建议从官方示例项目入手,熟悉后再自定义实现复杂系统。


参考资源#


UE5 Gameplay Ability System (GAS) 完全指南
https://gzhblog.cn/posts/2026-03/2026-03-30-ue5-gas-system/
作者
384400
发布于
2026-03-30
许可协议
CC BY-NC-SA 4.0

这篇文章是否对你有帮助?