前言

Deepseek介绍

UE(Unreal Engine)中的 GAS(Gameplay Ability System)是一套非常强大且灵活的游戏玩法技能框架,尤其适合用来构建复杂的战斗系统、技能和状态管理。下面这个表格能让你快速把握其核心组件。

组件名称 核心功能简介
Ability System Component (ASC) GAS的总协调中心,一个必须挂在Actor上的组件,负责管理所有GAS相关逻辑。
Gameplay Ability (GA) 定义一个完整的技能或能力(如攻击、跳跃、使用道具)的具体逻辑。
Gameplay Effect (GE) 代表一个效果或状态(如造成伤害、治疗、眩晕Buff),用于修改属性或添加/移除状态标签。
Attribute Set (AS) 定义和持有角色的数值属性(如生命值、魔法值、攻击力),并处理属性变化。
Gameplay Tag 一种层级标签系统,用于标记对象的状态、行为的分类,实现高效的逻辑判断和驱动。

💡 核心概念详解

为了让你更好地理解和使用GAS,下面是对上述组件的进一步说明:

  • Ability System Component (ASC) 这是GAS的“大脑”,任何想要使用GAS功能的Actor(如角色、怪物)都必须拥有这个组件。它负责管理Gameplay Ability的授予、激活、冷却,应用Gameplay Effect,以及维护Gameplay Tag和Attribute Set等。在网络游戏中,ASC应该放在何处(角色本身还是PlayerState上)是一个重要设计决策,会影响角色死亡重生等逻辑。
  • Gameplay Ability (GA) 一个技能(如“火球术”)就是一个GA。它包含了该技能从开始到结束的完整逻辑,例如:检查消耗、进入冷却、播放动画、产生伤害效果等。GA通常由事件驱动,例如响应玩家输入、被其他技能触发,或者满足特定标签条件时自动激活。
  • Gameplay Effect (GE) 这是GAS中用于改变游戏状态的主要工具。它非常灵活,可以通过配置实现多种效果:
    • 即时效果(Instant):立即改变属性,如造成直接伤害或治疗。
    • 持续效果(Duration / Infinite):在特定时长内或永久性地影响目标,如一个持续30秒的攻击力提升Buff,或一个每2秒触发一次的毒伤效果。
  • Attribute Set (AS) 它集中定义了角色所有的数值属性(如Health、Mana、Stamina),并提供了属性值变化前后的回调函数,方便你处理逻辑(如确保生命值不会低于0)。AS中的属性通常包含一个基础值(BaseValue) 和一个当前值(CurrentValue)
  • Gameplay Tag 这种标签具有层级结构(例如 State.Buff.MovementSpeed),可以非常精确地描述和查询一个对象的状态。在GAS中,Tag被广泛用于:控制技能能否释放(如角色拥有 State.Stunned标签时无法使用大多数技能)、定义技能间的互斥关系、以及触发特定的Gameplay Ability。

🛠️ 使用GAS的基本步骤

  1. 启用插件:在UE编辑器的“插件”管理器中,找到并启用 “Gameplay Abilities” 插件。
  2. 设置项目模块:在项目的 .Build.cs文件中添加 "GameplayAbilities", "GameplayTags", "GameplayTasks"模块依赖。
  3. 创建ASC:让你的角色C++类继承 IAbilitySystemInterface接口,并在构造函数中创建 UAbilitySystemComponent的实例。
  4. 定义属性:创建一个继承自 UAttributeSet的C++类,并在其中定义所需的属性(如 HealthMana)。
  5. 授予技能:在角色初始化时(如 BeginPlay中),通过ASC的 GiveAbility函数将技能赋予角色。

⚙️ 进阶特性与调试

  • 网络复制与预测:GAS为多人游戏提供了强大的支持,包括状态同步和客户端预测(例如,客户端可以立即响应输入施展技能,无需等待服务器确认,如果预测错误则由服务器进行纠正)。
  • 调试命令:GAS提供了方便的调试命令,帮助你在开发过程中可视化内部状态:
    • ShowDebug AbilitySystem:在屏幕上显示GAS调试信息。
    • AbilitySystem.Debug.NextCategory:切换查看属性(Attributes)、技能(Ability)或效果(GameplayEffects)等不同类别的信息。

希望这份概述能帮助你建立起对UE GAS系统的整体认识。如果你对其中某个特定组件(比如如何具体编写一个Gameplay Ability)有更深入的兴趣,我们可以继续展开讨论。

GT(Gameplay Tags)

GameplayTags是一个内置的插件,不属于GAS。

角色本身的枚举、布尔等状态(非属性)变量也可以用Tag储存,非常好用,我自己的用法是在让AI在行为树的Decorator节点中,通过玩家拥有的Gameplay Tag来判断玩家是否处于无敌帧、喝药。

在每个模块中最好设置上自己的命名空间前缀,避免整个系统的Tag混乱。

ACS(Ability System Component)

Ability System Component(ASC)是整个GAS的基础组件。
ASC本质上是一个UActorComponent,用于处理整个框架下的交互逻辑,包括使用技能 (GameplayAbility)、包含属性(AttributeSet)、处理各种效果(GameplayEffect)。
所有需要应用GAS的对象(Actor),都必须拥有GAS组件。
拥有ASC的Actor被称为ASC的OwnerActor,ASC实际作用的Actor叫做AvatarActor。ASC可以被赋予某个角色ASC,也可以被赋予PlayerState(可以保存死亡角色的一些数据

GA(Gameplay Ability)

Gameplay Ability(GA)标识了游戏中一个对象(Actor)可以做的行为或技能。 能力(Ability)可以是普通攻击或者吟唱技能,可以是角色被击飞倒地,还可以是使用 某种道具,交互某个物件,甚至跳跃、飞行等角色行为也可以是Ability。
Ability可以被赋予对象或从对象的ASC中移除,对象同时可以激活多个GameplayAbility。 基本的移动输入、UI交互行为则不能或不建议通过GA来实现

img

角色需要拥有GA后,才能使用GA。

GA的使用分为实例化释放两个过程,前者主要是生成一个FGameplayAbilitySpec对象,并为一部分非公有(非静态)属性赋值,如当前GA的等级。后者操作的实际对象则为Spec。

可以把Spec理解为GA的实例,GE等其他类也有相似的概念。\

通常来说,使用GA时不用去考虑两个过程的区别,除非你需要在实例化Spec后,手动修改一些在GA类上定义好的属性再去手动释放。在GE篇会详细介绍,用于实现技能的冷却、消耗。

添加GA

如果不使用C++修改,只能通过GE去添加GA,非常不方便。

  • 在角色类中创建一个数组,游戏启动时自动添加数组里的GA
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
.h 
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Abilities")
TArray<TSubclassOf<class UGameplayAbility>> PreloadedAbilities;
===========================
.cpp BeginPlay遍历数组
Super::BeginPlay();
if (AbilitySystemComponent != nullptr)
{
//初始化技能
if (PreloadedAbilities.Num() > 0)
{
for (auto i = 0; i < PreloadedAbilities.Num(); i++)
{
if (PreloadedAbilities[i] != nullptr)
{
// FGameplayAbilitySpec是GA的实例,其构造函数的第二个参数代表GA的等级,这里暂令其全部为1
AbilitySystemComponent->GiveAbility(
FGameplayAbilitySpec(PreloadedAbilities[i].GetDefaultObject(), 1));
}
}
}

//初始化ASC
AbilitySystemComponent->InitAbilityActorInfo(this, this);
}
===========================
.BP
//在角色蓝图的details面板找到数组,填好GA。
  • 在角色蓝图中使用Give Ability函数手动添加Ability

AbilitySystemComponent->GiveAbility()方法在蓝图中无法使用,这边自己封装了一个GiveAbility().

这是一个将ASC中未暴露给蓝图的函数进行封装的例子,如果想在蓝图中使用其他的ASC函数可以进行参考。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
.h
//添加Ability
UFUNCTION(BlueprintCallable, Category = "Ability System")
void GiveAbility(TSubclassOf<UGameplayAbility> Ability, int32 Level = 1);
===========================
.cpp
void ACharacterBase::GiveAbility(TSubclassOf<UGameplayAbility> Ability, int32 Level)
{
if (AbilitySystemComponent)
{
if (HasAuthority() && Ability)
{
AbilitySystemComponent->GiveAbility(FGameplayAbilitySpec(Ability, Level));
}
AbilitySystemComponent->InitAbilityActorInfo(this, this);
}
}
===========================
.BP
BeginPlay->GiveAbility

  • 使用GE添加GA

GE(Gameplay Effect)

Gameplay Effect(GE)是Ability对自己或他人产生影响的途径。 GE通常可以被理解为我们游戏中的buff。比如增益/减益效果(修改属性)。
但是GAS中的GE也更加广义,释放技能时候的伤害结算,施加特殊效果的控制、霸体效果 (修改GameplayTag)都是通过GE来实现的。
GE相当于一个可配置的数据表,不可以添加逻辑。开发者创建一个UGameplayEffect的派 生蓝图,就可以根据需求制作想要的效果。

AS(Attribute Set)

AttributeSet 负责定义和持有属性,并且管理属性的变化,包括网络同步。 需要在Actor中被添加为成员变量,并注册到ASC(C++)。
一个ASC可以拥有一个或多个(不同的)AttributeSet,因此可以角色共享一个很大的 Attribute Set,也可以每个角色按需添加Attribute Set。
可以在属性变化前(PreAttributeChange)后(PostGameplayEffectExecute)处理相关 逻辑,可以通过委托的方式绑定属性变化。

正如字面意思,AS是Attribute的集合。

Attribute就是HP、MP、Speed、ATK等可以用float表示的属性。

因为Attribute是包含了两个float变量的结构体,分别是Base Value和Current Value。

Base Value表示基础值,Current Value表示临时值。

如临时增加100生命值10s,改变的就是Current Value,10s后自动变回Base Value。

做GE时要注意修改的是哪种Value

AS只能使用C++创建。

修改事件

  • PreAttributeChange:用于Attribute的Current Value被改变前调用,对应Infinite和Has Duration的GE。
  • PostGameplayEffectExecute:用于Base Value改变后调用,对应InstantGE。
  • GetGameplayAttributeValueChangeDelegate:监听Attribute的变化以更新UI,则不适合用上面的方法,应该在角色类中创建一个回调,以及蓝图事件

GC(Gameplay Cues)

GameplayCues (GC) 执行非游戏性相关的事情,比如音效,粒子特效,震屏等。GameplayCues通常会被复制和预测(除非设置Executed, AddedRemoved是本地的)。

网络预测

客户端使用技能,客户端和服务器都需要执行,而且很多结果需要服务器的权威验证。但事事都等待服务器验证,就会有网络延迟问题,操作体验不佳,为了避免延迟,GAS支持本地预测执行GA,和预测添加GE。把GA的NetExecutionPolicy属性设置为LocalPredicted,就能让GA支持网络预测执行。

可以本地预测的

  • 激活GA
  • Trigger Events
  • 生效GE
  • 生效GC
  • 蒙太奇动画

本地不可以预测的

  • GE移除
  • GE的周期性操作

预测执行框架的重点是客户端与服务器不一致时,如何回滚客户端的操作。

参考

【Unreal】虚幻GAS系统快速入门 - 知乎

用Unity制作一个极具扩展性的顶视角射击游戏战斗系统 - 知乎

基于 Unreal Lyra 的 GAS 属性扩展和应用 - 知乎

UE5 GAS - 以Lyra为例 - 知乎

GitHub - BillEliot/GASDocumentation_Chinese