GAS初步(Gameplay Ability System)

原本是打算实战运动系统的,由于资源包还在准备,正好这周上班摸鱼时看了看GAS,于是今天再研究下做个笔记。

Gameplay Tags

FGameplayTags是一种层级标签,如Parent.Child.GrandChild。
通过GameplayTagManager进行注册。替代了原来的Bool,或Enum的结构,可以在玩法设计中更高效 的标记对象的行为或状态。

在学习GAS之前,必须先了解一下这个,因为GAS会大量使用Tag。

与通常Tag类似,使用GameplayTagContainer即可绑定Tag容器到指定对象上。只不过GameplayTag是带层级关系的标签如: character.debuff.slow 这样可以对tag分类或追根溯源。比如游戏中有种道具可以清除角色身上所有debuff,则使用character.debuff 即可匹配到所有debuff。

对Tag或者Container的基础查询,可以用以下函数:

函数 输入参数 返回值
A.1 MatchesTag A true
A.1 MatchesTagExact A false
A.1 MatchesAny {A,C} true
A.1 MatchesAnyExact {A,C} false
A.1 MatchesAll {A} true
A.1 MatchesAllExact {A} false
{A.1,B.1} HasTag A true
{A.1,B.1} HasTagExact A false
{A.1,B.1} HasAny {A,C} true
{A.1,B.1} HasAnyExact {A,C} false
{A.1,B.1} HasAll {A,B} true
{A.1,B.1} HasAllExact {A,B} false

FGameplayTagQuery 可以 使用 FGameplayTagQuery build一些更复杂的查询

Gameplay Ability System

GAS主要包含以下内容:

  • ASC (Ability System Component) 技能系统核心组件。
  • GA (Gameplay Abilities) 角色的技能,例如攻击,施法等。
  • AS (Attribute Set) 角色的属性,例如生命值,体力值等。
  • GE (Gameplay Effects) 用于修改属性,或者叫Buff。
  • GC (Gameplay Cues) 通知用于回调播放特效或音效。

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,可以保存死亡角色的一些数据

简单来说,ASC是一种角色组件,负责和GA、GE、AS打交道。

在角色.h中声明

1
2
3
4
public:
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "GAS")
class UAbilitySystemComponent* AbilitySystemComponent;

初始化

1
AbilitySystemComponent = CreateDefaultSubobject<UAbilitySystemComponent>(TEXT("AbilitySystemComponent"));

Gameplay Ability

Gameplay Ability 源自 UGameplayAbility 类,定义了游戏中技能的效果、使用技能付出的代价(如有),以及何时或在何情况下可以使用等。玩法技能可以作为异步运行的实例化对象存在,因此你可以运行专门的多阶段任务,包括角色动画、粒子和声效,乃至根据执行时的用户输入或角色交互设计分支。玩法技能可以在整个网络中自我复制,运行在客户端或服务器计算机上(包括客户端预测支持),甚至还能同步变量和执行远程过程调用(RPC)。玩法技能还使引擎可在游戏会话期间灵活实现游戏技能,例如提供的扩展功能可用于实现冷却和使用消耗、玩家输入、使用动画蒙太奇的动画,以及对给予Actor的技能本身做出反应。

在Actor可以使用某项技能之前,必须向其技能系统组件授予该技能。

  • GiveAbility
  • GiveAbilityAndActivateOnce 仅一次

基本用法

  1. 即使调用者没有尝试执行某项技能,CanActivateAbility也可以让调用者知道是否可执行该技能。例如,您可以在户界面上将玩家无法使用的图标变成灰色并停用这些图标,或者对角色播放声音或粒子效果来显示某项技能是否可用。

  2. CallActivateAbility执行技能相关的游戏代码,但不会检查该技能是否可用。通常在 CanActivateAbility检查及执行技能之间需要某些逻辑时才会调用该函数。

  3. TryActivateAbility 是执行技能的典型方式。该函数调用 CanActivateAbility 来确定技能是否可以立即运行,如果可以,则继续调用 CallActivateAbility

初始化默认技能
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="GAS")
TArray<TSubclassOf<class UGameplayAbility>> InitAbilities;


void AGASLearning01Character::InitDefaultAbility()
{
if (AbilitySystemComponent == nullptr || InitAbilities.IsEmpty()) return;
for (const TSubclassOf<class UGameplayAbility> Ab : InitAbilities)
{
if (Ab != nullptr)
{
AbilitySystemComponent->GiveAbility(Ab);
}
}
}

在蓝图编写一个GA_AddHealth

在编辑器添加GA

尝试激活GA

Attribute Set

游戏属性会保持一个当前值和基础值,”当前”值是大多数计算和逻辑会使用的值,并且会受到当前活跃的游戏效果的影响,而”基础”值则倾向在较长时间内保持固定。 举个例子,”跳跃高度”游戏玩法属性的基础值可能是100.0,但如果该角色有一个主动的[游戏玩法效果],显示角色累了,只能跳到正常高度的70%,那么当前值就是70.0。如果该角色发生永久性改变,变得更善于跳跃,这可能是通过等级提升系统实现的,那么基础值可能会增加到110.0,而只要[游戏玩法效果]还在,当前值就会被计算为77.0。

定义

UMyAttributeSet.cpp
1
2
3
4
5
6
7
8
9
10
UCLASS()
class MYPROJECT_API UMyAttributeSet : public UAttributeSet
{
GENERATED_BODY()

public:

UPROPERTY(EditAnywhere, BlueprintReadOnly)
FGameplayAttributeData Health;
};

使用

1
2
UPROPERTY()
const UMyAttributeSet* AttributeSet;
1
2
3
4
5
AbilitySystemComponent* ASC = GetAbilitySystemComponent();
if (IsValid(ASC))
{
AttributeSet = ASC->GetSet<UMyAttributeSet>();
}

与游戏效果互动,重写 PostGameplayEffectExecute

1
2
3
4
5
6
7
8
9
void UMyAttributeSet::PostGameplayEffectExecute(const struct FGameplayEffectModCallbackData& Data)
{
Super::PostGameplayEffectExecute(Data);
if (Data.EvaluatedData.Attribute == GetHealthAttribute())
{
SetHealth(FMath::Max(GetHealth(), 0.0f));
}
}

重载属性集函数

  • PreAttributeChange / PreAttributeBaseChange 这些函数在即将修改属性之前调用。函数旨在实施关于属性值的规则,例如,”生命值必须介于0和最大生命值”之间,并且不得对属性更改触发游戏内响应。

  • PreGameplayEffectExecute 在即将修改属性值之前,此函数可以拒绝或更改拟定修改。

  • PostGameplayEffectExecute 在修改属性值后,此函数可立即对更改做出响应。这通常包括限制属性的最终值或触发对新值的游戏内响应,例如当”生命值”属性降至零时死亡。

Gameplay Effects

Gameplay技能系统会利用 Gameplay效果 更改Gameplay技能所针对Actor的属性。Gameplay效果包含你可以应用到Actor属性的函数库。这些效果可以是即时效果,比如施加伤害,也可以是持续效果,比如毒杀,在一定的时间内对角色造成伤害。

Gameplay效果生命周期

Gameplay效果的 时长(Duration) 可设置为 即时(Instant) 、 无限(Infinite) 或 有持续时间(Has Duration) 。 具有持续时间的Gameplay效果将添加到 激活Gameplay效果容器(Active Gameplay Effects Container) 。激活Gameplay效果容器是技能系统组件的一部分。

Gameplay效果组件

Gameplay效果包含用于确定Gameplay效果如何呈现的 Gameplay效果组件 (GEComponents)。

使用GE初始化角色AttributeSet

新建一个GE_InitAttr蓝图类, 找到Gameplay Effect条目。

一个Modifiers对应一个Attributes。然后在蓝图中Apply该GE即可。

可实现的效果可以非常复杂! 而这仅需配置而已,不用一行代码。