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

一、GameplayTags与GAS

1.1 GameplayTags

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

但是GAS会大量使用Tag,在编辑-项目设置里可以找到。

GA、GE、GameplayEvent、GameplayCue都会大量使用Tag。如果你还不懂这些名词的含义,可以先往后看。

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

但因此Tag的层级关系也需要合理设计,到了后期修改成本比较大。

个人的建议是设计Ability、Effect、GameplayCue、Event、Character、Cooldown等基础标签,在对应的模块只检测对应的Tag(比如监听动画通知发送的Event,就可以是Event.AnimNotify.Fire),避免重复或者模糊定义。

举一个反面例子,比如将Attack的GA标签和GE标签、角色处于攻击状态的标签都设置为Character.Attack,不利于追述Tag的来源。

其他的Tag可以根据需求添加,如Item等。

同时要注意,Tag的父子关系也要考虑的,若合理设计,可以用于批量筛选同一类Tag。

在Editor内批量修改Tag可能不是那么方便,这里有一个比较好的管理方法:
《Ue4Config方法总结与另外一种GameplayTag管理方法》

1.2 Gameplay Ability System
GAS主要包含以下内容:

  • ASC(Ability System Component)主要组件,由C++编写,代码里有很多方法是蓝图未实现的。
  • GA(Gameplay Abilities)角色的技能,包括攻击、疾跑、施法、翻滚、使用道具等,但不包括基础移动和UI。
  • AS(Attribute Set)角色身上可以用float表示的属性,如生命值、体力值、魔力值等。
  • GE(Gameplay Effects)用于修改属性,如增加50移动速度10s;还能配合GA实现更多玩法。
  • GC(Gameplay Cues)播放特效、音效等。

如果看过《深入GAS架构设计》,可以发现应该还有Task和Event两个额外功能。

严格意义上这两个功能和Tag一样是UE原生内容,在GA部分比较常用,因此本文选择将其放在GA部分讲解。

二、Ability System Component

2.1 ASC组件介绍

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打交道。

一般只放在Character or PlayerState上,在武器上加ASC组件也不是不行,但是并没有很好的实践供参考,官方文档提到过这一点。

OwnerActor和AvartarActor是比较常见的概念,如果ASC在Character类身上,那么二者是相同的。

如果Character需要销毁再重新生成,如MOBA游戏角色死亡后泉水复活,那么ASC可以放在PlayerState上避免随着角色一同销毁。此时的OwnerActor是PlayerState,AvatarActor则是Character。

学习动画系统后的一些补充想法:如果希望角色部分为纯蓝图实现,以便直接指定父类为一些模板角色蓝图,如ALSv4,这种情况下也许放在PlayerState里会更好?

2.2 添加ASC组件
一开始的设置需要一些C++,这里IDE建议使用Rider for Unreal,会自动补全一些头文件声明,防止遗漏。

C++基础知识补充:

UE的C++类分为两部分,一个是.h头文件,一个是.cpp文件。

属性和方法的声明写在.h文件里,方法的实现写在.cpp里,包括构造函数。

在进行接下来的操作之前,你需要自己创建一个继承自ACharacter的C++类,如下图的ARPGCharacterBase。(图源右下角)

之后想用蓝图,就从这个自定义的C++Character类派生就可以了。

图源@开发游戏的老王

1、角色.h中声明ASC。

 

arduino

复制代码

#include "AbilitySystemComponent.h" public: UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Abilities") class UAbilitySystemComponent* AbilitySystemComponent;

不要忘了在项目Build.cs文件的PrivateDependencyModuleNames里加上“GameplayAbilities”,“GameplayTags”,“GameplayTasks”三个模块。

2、在.cpp中构造函数部分实例化ASC。

 

ini

复制代码

//实例化ASC AbilitySystemComponent = CreateDefaultSubobject<UAbilitySystemComponent>(TEXT("AbilitySystem"));

3、角色类继承IAbilitySystemInterface接口,并实现GetASC函数。

 

arduino

复制代码

#include "AbilitySystemInterface.h" class ARPG_UNREAL_API ACharacterBase : public ACharacter, public IAbilitySystemInterface public: UAbilitySystemComponent* GetAbilitySystemComponent()const override;

.cpp

 

arduino

复制代码

UAbilitySystemComponent* ACharacterBase::GetAbilitySystemComponent()const{return AbilitySystemComponent;}

上面的示例代码使用的是原生的ASC组件。如果想自己继承一个ASC子组件封装一些功能,可以参考官方的Action RPG实例项目里的写法。

2.3 ASC组件的功能
GAS的大部分功能都在ASC组件的源码中,并且只有一部分暴露给了蓝图,有些功能如添加GA(见3.2)还需要通过代码实现。由于本文只是一篇快速入门手册,不再过多赘述。

想要详细了解GAS系统,可以先从ASC组件的源码入手,有时可以避免重复造轮子。

具体的功能会在下文使用到。

三、Gameplay Ability

3.1 GA介绍

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

一个GA蓝图大概就长这样

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

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

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

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

3.2介绍GA的不同获得方式,3.3介绍GA蓝图的制作,3.4介绍GA的使用。

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

这里介绍两种修改方法。

3.2.1 在角色类中创建一个数组,游戏启动时自动添加数组里的GA
注意:使用这一种方法不易控制每个GA的初始等级。

1、在角色头文件声明数组:

 

swift

复制代码

public: // 将在游戏启动时被赋予角色的Abilities数组 UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Abilities") TArray<TSubclassOf<class UGameplayAbility>> PreloadedAbilities;

2、在角色的BeginPlay()里遍历数组,使用AbilitySystemComponent->GiveAbility()添加Ability:

 

scss

复制代码

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); }

3、在角色蓝图的Details面板找到数组,填好GA。

如果后面做完一个GA发现没反应,可能就是忘记Give刚做好的GA给角色了,或者场景中的角色对象拥有的技能没有和类默认值同步。

3.2.2 在角色蓝图中使用Give Ability函数手动添加Ability
上面提到的AbilitySystemComponent->GiveAbility()方法在蓝图中无法使用。

为了在蓝图中动态添加Ability,我们需要在蓝图中实现自己的GiveAbility()。

按理说在自己的ASC子类中实现最好,这里在角色蓝图中实现。

1、CharacterBase.h

 

ini

复制代码

public: //添加Ability UFUNCTION(BlueprintCallable, Category = "Ability System") void GiveAbility(TSubclassOf<UGameplayAbility> Ability, int32 Level = 1);

2、CharacterBase.cpp

 

scss

复制代码

void ACharacterBase::GiveAbility(TSubclassOf<UGameplayAbility> Ability, int32 Level) { if (AbilitySystemComponent) { if (HasAuthority() && Ability) { AbilitySystemComponent->GiveAbility(FGameplayAbilitySpec(Ability, Level)); } AbilitySystemComponent->InitAbilityActorInfo(this, this); } }

使用例

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

3.2.3 使用GE添加GA
新建一个GE,在Granted Abilities条目里添加的GA都会在GE被Apply到角色身上时赋予(Grant)。

参数的具体含义详见5.2.10。

然后在蓝图里调用Apply GameplayEffect to Self节点即可(这里的Level是GE的等级,不是GA)。

3.3 制作GA

### 虚幻引擎中的GAS(Gameplay Ability System) #### GAS的核心功能 Gameplay Ability System (GAS) 是虚幻引擎的一个内置插件,提供了强大的框架来实现角色技能、属性系统以及状态效果等功能。它支持复杂的数值计算、能力消耗与冷却机制,并集成了网络同步和预测功能[^3]。 #### 插件激活 要在项目中使用 GAS,需先在插件管理器中启用该插件。一旦启用,可以通过 `AbilitySystemComponent` 来管理和执行各种能力和属性操作。 #### 主要组成部分 1. **Abilities(能力)** Abilities 定义了游戏中可触发的行为或动作,例如攻击、施法或其他交互行为。它们通常绑定到特定输入事件并具有自己的逻辑脚本。每个 Ability 可以设置资源成本(如生命值或能量)、持续时间及冷却周期。 2. **Attributes(属性)** Attributes 表示实体的基础数据项,比如健康度、耐力或者力量等级等。这些动态变化的数据由 `AttributeSet` 类型定义并通过 `AbilitySystemComponent` 进行更新维护。 3. **Effects(效果)** Effects 用于描述当某个条件满足时所发生的变化,可能涉及修改目标单位的一系列参数或是附加特殊标记(Tag)。常见的例子有伤害加成、减速惩罚等等。 4. **Gameplay Tags 和 Gameplay Events** - **Gameplay Tags**: 提供了一种灵活的方式来分类和检索游戏内的元素。几乎所有的核心结构都支持关联标签以便于查询匹配。 - **Gameplay Events**: 允许广播自定义消息给监听者列表从而驱动复杂互动链路的发生发展过程。 5. **Network Replication & Prediction** 鉴于多人在线环境下的需求考量,GAS 设计之初就充分考虑到了跨客户端间一致性保障的重要性,因此包含了完备可靠的网路传输解决方案. #### 示例代码展示如何创建简单的Skill System基于GAS: ```cpp // MyCharacter.h UCLASS() class MYPROJECT_API AMyCharacter : public ACharacter { GENERATED_BODY() public: UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Components") UAbilitySystemComponent* AbilitySystemComp; protected: virtual void BeginPlay() override; }; // MyCharacter.cpp #include "MyCharacter.h" #include "AbilitySystemBlueprintLibrary.h" AMyCharacter::AMyCharacter(const FObjectInitializer& ObjectInitializer) { AbilitySystemComp = CreateDefaultSubobject<UAbilitySystemComponent>(TEXT("AbilitySystemComp")); } void AMyCharacter::BeginPlay() { Super::BeginPlay(); if(AbilitySystemComp && HasAuthority()) { // Grant abilities on server side only. FGameplayAbilitySpecDef SpecDef; SpecDef.Ability = StaticClass()->FindFunctionByName(FName(TEXT("ExecuteBasicAttack"))); SpecDef.InputID = EInputAction::IA_BasicAttack; // Assuming you have this enum defined elsewhere const TArray<FGameplayEffectContextHandle> ContextHandles; AbilitySystemComp->GiveAbility(SpecDef); // Initialize default attributes here... } } ``` 上述片段展示了怎样在一个继承自ACharacter类的新角色身上添加基本战斗技巧的能力授予方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值