UE5GAS框架入门介绍
前言
GAS(Gameplay Ability System)是UE5中用于快速搭建MOBA(比如英雄联盟)、FPS(比如穿越火线、CS)等游戏技能系统的强大框架。
为什么需要GAS?
如果你已经能用UE5的蓝图和动画系统做出一个能跑能跳、会放几个简单技能的角色,那你肯定遇到过下面这些“糟心事儿”。
- 比如,想给角色加个“生命值”属性,结果发现这个值要在UI上显示、要被技能伤害扣除、还要被治疗技能恢复,不得不在蓝图的各个角落里写上一堆“Set Health”、“Get Health”的节点,稍微改点逻辑就得满世界找。
- 再比如,想做个“火球术”技能,要有施法动作、飞行轨迹、碰撞伤害,还得有个冷却时间,可能得用一个状态机、一堆定时器、再加上事件分发器才能勉强拼出来,代码(或者蓝图)乱得像一团麻。
刚开始开发的时候,都是通过基类硬写的。如果项目里的技能数量上了两位数,各种状态效果纠缠在一起,才意识到,是时候找个“管家”了。这个管家,就是GameplayAbilitySystem,我们通常叫它GAS。
可以把GAS理解为游戏中所有“规则”和“能力”的中央管理系统。它帮管好角色的属性(比如生命、魔法、攻击力),管好角色的技能(比如普攻、火球、闪现),还管好技能带来的效果(比如中毒掉血、加速Buff)。最重要的是,它天生就为网络同步设计好了。这意味着,费老大劲在本地调好的技能,在多人联机时,大概率不会出现“我打中了你,你却没事”这种灵异事件。
介绍原理
GAS框架主要由以下几个模块构成
1. AbilitySystemComponent(ASC):能力系统的组件,用于管理玩家拥有哪些能力,并通过该组件尝试使用对应能力
2. GameplayAbility(GA):具体的能力,每种能力对应一种或多种效果
3. GameplayAttribute:持有能力组件的拥有者的属性,比如最大生命值,生命值,攻击力等
4. AttributeSet(AS):在C++中修改,是GameplayAttribute的集合,放置所有属性
5. GameplayEffect(GE):技能效果,可以由ASC或GA释放,通常用于为玩家添加标签,或者修改玩家的属性等
6. GameplayCue(GC):用于播放特效,音效,镜头摇晃等视觉效果
7. AbilityTask:UE内置了许多任务,在GA中可以用到,比如移动当前玩家位置,播放动画蒙太奇等
8. GameplayTags:本身并不属于GAS系统,但是GAS系统大量用到,本质是一个可以动态增删的标签,可以起到类似枚举的作用,冷却,条件判断都可以用到
准备阶段
1.创建C++第三人称项目(不能用纯蓝图)
GAS的核心功能是通过 C++ 类暴露给蓝图的,纯蓝图项目无法使用GAS的全部威力(尤其是网络部分)。如果现在还是纯蓝图项目,建议立刻把它升级为 C++ 项目,很简单,在编辑器里选择“工具”->“新建C++类…”,随便创建一个类(比如MyGameMode),UE5就会自动为你生成所需的VS项目文件。
2.在插件设置中启用GameplayAbilities插件
在Build.cs文件中添加"GameplayTags",“GameplayTasks”,“GameplayAbilities”,三个模块依赖。
在顶部菜单栏找到 “编辑” -> “插件”。会弹出一个庞大的插件窗口。
在右上角的搜索框里,输入 “Gameplay”。
三个关键的插件:
- Gameplay Abilities
- Gameplay Tags
- Gameplay Tasks
确保这三个插件旁边的复选框都是已启用(打勾)状态。如果之前没启用,勾选后,编辑器会提示需要重启。放心点击重启,这是标准操作。
注意:Gameplay Tags(游戏标签)是GAS的“语言系统”,技能、状态、效果都用它来标识和查询,至关重要。Gameplay Tasks则用于管理一些异步任务
3.在C++项目中添加模块依赖
插件启用只是让编辑器认识GAS了,要让C++代码能调用GAS的类,还需要在编译层面建立依赖关系。
找到项目源代码文件夹。通常在项目根目录下,有一个Source文件夹,里面有项目名的子文件夹(例如MyGasProject)。
在这个文件夹里,找到一个名为 [项目名].Build.cs 的文件。比如我的项目叫GasDemo,那这个文件就是GasDemo.Build.cs。
用文本编辑器(或VS Code)打开它。会看到类似下面的代码:
1 | using UnrealBuildTool; |
需要修改的是PublicDependencyModuleNames.AddRange这一行。把刚才在插件窗口看到的三个模块名字加进去:
1 | PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "GameplayAbilities", "GameplayTags", "GameplayTasks" }); |
创建核心组件:ASC与AttributeSet
GAS有两个基石般的组件:Ability System Component (ASC) 和 Attribute Set (AS)。可以把ASC想象成角色的“技能大脑”,所有技能的激活、冷却、状态管理都由它负责。而Attribute Set则是角色的“属性仓库”,专门存放生命值、魔法值、力量、敏捷这些数值。
4.1 创建自定义的ASC(可选但推荐)
虽然可以直接把引擎自带的UAbilitySystemComponent挂到角色上,但我强烈建议角色创建一个子类。这样未来可以很方便地添加一些自定义逻辑,比如记录角色拥有的技能列表,或者覆写一些网络同步的回调函数。
在内容浏览器的 C++ 类文件夹上右键,选择“新建C++类”。在搜索框里输入AbilitySystemComponent,选择它作为父类,给类起个名字,比如MyAbilitySystemComponent。创建完成后,暂时不需要在里面写任何代码,它代表了“这是我的技能系统组件”。
4.2 创建属性集(Attribute Set)
属性集是定义游戏数值的地方。比如创建一个最基础的,只包含生命值和最大生命值。
同样,右键新建C++类,这次父类选择AttributeSet,类名可以叫MyAttributeSet。
打开生成的MyAttributeSet.h头文件,我们需要在里面定义属性。GAS的属性不是普通的float变量,而是用特殊的宏UPROPERTY(BlueprintReadOnly, ReplicatedUsing = OnRep_Health, Category = “Attribute”)来声明,并且需要配套的Getter/Setter函数和复制回调函数。
下面是一个定义了Health(当前生命值)和MaxHealth(最大生命值)的属性集头文件示例:
1 | // MyAttributeSet.h |
在对应的.cpp文件中,需要实现这些函数,特别是网络复制部分:
1 | // MyAttributeSet.cpp |
关键点:属性用FGameplayAttributeData类型声明,并用ATTRIBUTE_ACCESSORS宏来生成便捷函数,同时必须处理好网络复制(ReplicatedUsing和GetLifetimeReplicatedProps)。
4.3 将组件挂载到角色
想为玩家添加ASC组件,需要修改角色类(通常是继承自ACharacter的C++类),除了为它添加一个UPROPERTY标记的蓝图可见的UAbilitySystemComponent属性外,还需要让该类继承自IAbilitySystemInterface接口并实现对应接口。
打开角色类头文件(例如MyCharacter.h),添加以下代码:
1 | // MyCharacter.h |
在角色类的实现文件(.cpp)中,需要在构造函数或BeginPlay中创建并初始化这些组件:
1 | // MyCharacter.cpp |
至此,角色已经拥有了GAS的核心骨架。编译项目,如果没有错误,最基础也是最繁琐的配置工作已经完成了!
实现第一个技能:GameplayAbility
技能(GameplayAbility,简称GA)是GAS中代表一个可激活能力的单位。一个火球术、一次跳跃、一次格挡,都可以是一个GA。我们来创建一个最简单的火球术GA,它需要做几件事:检查能否释放(比如魔法值够不够)、播放施法动画、生成一个投射物、进入冷却。
1 创建GameplayAbility类
右键新建 C++ 类,父类选择GameplayAbility,起名例如GA_Firebolt。GAS的GA类通常以GA_前缀命名,方便管理。
打开GA_Firebolt.h,会看到它继承自UGameplayAbility。暂时不需要添加新的变量,但需要了解几个关键的可重写函数:
- CanActivateAbility:检查技能是否可以释放。这里可以检查角色是否死亡、是否处于眩晕状态等。
- ActivateAbility:技能激活时调用的主函数。在这里编写技能的主要逻辑。
- EndAbility:技能结束时调用(无论成功、取消还是失败)。
- InputPressed / InputReleased:处理技能按键输入。
对于火球术技能,主要关注ActivateAbility。想让它在服务器上执行核心逻辑(生成投射物),在客户端上播放动画和音效(表现)。
2 编写火球术逻辑( C++部分)
先在头文件里声明一个UFUNCTION,用于在服务器上生成火球投射物。
1 | // GA_Firebolt.h |
在.cpp文件中,实现它。为了简化,假设已经有一个蓝图类BP_FireboltProjectile,它继承自Actor或Projectile移动组件,负责飞出去并检测碰撞。
1 | // GA_Firebolt.cpp |
以上代码是一个高度简化的示例,重点展示了GA的结构:在ActivateAbility中检查条件、播放动画、通过任务等待动画完成、然后在服务器上生成投射物。在实际项目中,BP_FireboltProjectileClass需要通过UPROPERTY(EditDefaultsOnly)在编辑器中指定,动画蒙太奇也需要妥善引用。
3 在蓝图中配置技能并赋予角色
C++ 类写好后,编译项目。然后在内容浏览器中右键 -> 蓝图类 -> 所有类中搜索 GA_Firebolt,基于它创建一个蓝图,例如BP_GA_Firebolt。
在这个蓝图中,可以做很多可视化配置:
- 冷却时间(Cooldown):添加一个GameplayEffect(后面会讲)来定义技能冷却。
- 消耗(Cost):添加另一个GameplayEffect来定义释放技能消耗的魔法值。
- 技能标签(Ability Tags):给技能打上标签,比如Ability.Spell.Fire,方便其他系统识别。
接下来,需要把这个技能赋予给角色。
有几种方式,最简单的是在角色的蓝图里,在BeginPlay事件中,调用其AbilitySystemComponent的GiveAbility函数,将BP_GA_Firebolt的类赋予给它。同时,还需要在角色的输入设置中,绑定一个按键(如鼠标左键)来触发这个技能(通过调用AbilitySystemComponent->TryActivateAbilityByClass)。
为技能添加效果:GameplayEffect与GameplayCue
技能放出去了,但它现在只是个“空壳”。需要两个东西来让它完整:GameplayEffect (GE)来定义它的“规则”(比如伤害多少、冷却多久),和GameplayCue (GC)来定义它的“表现”(比如命中时的爆炸特效和音效)。
1 创建冷却与消耗的GameplayEffect
GameplayEffect是GAS中修改属性和应用状态的核心数据资产。它不包含逻辑,只包含配置。为火球术创建两个GE:
- 冷却GE:一个Duration(持续时长)类型的GE,持续时间为5秒。它本身不修改任何属性,但拥有一个Cooldown标签(如Cooldown.Firebolt)。当这个GE在技能上激活时,技能在5秒内无法再次使用。
- 消耗GE:一个Instant(瞬时)类型的GE,在技能释放时立即扣除角色的魔法值(Mana)。这需要在
AttributeSet中先定义好Mana属性。
创建GE非常简单,在内容浏览器中右键 -> 蓝图类 -> 所有类中搜索 GameplayEffect,然后选择Instant或Duration类型创建即可。在GE的蓝图中,可以:
- 在Modifiers(修饰器)列表中添加一条,选择AttributeSet中的Mana属性,设置Modifier Op为Add(相加),Magnitude为-20.0(表示扣除20点)。
- 在Granted Tags(授予标签)或Gameplay Effect Tags(GE标签)中添加冷却标签。
然后,回到技能蓝图BP_GA_Firebolt,在Ability Details面板中,找到Cooldown和Cost选项,分别将创建的冷却GE和消耗GE拖进去。这样,GAS框架就会在技能激活时自动应用这些效果。
2 创建命中的GameplayCue
GameplayCue用于处理与游戏逻辑无关的视听表现。火球命中目标时,想播放一个爆炸粒子和音效。
首先,需要创建一个GameplayCue通知类。在C++中,新建一个类继承自UGameplayCueNotify_Static(一次性效果)或UGameplayCueNotify_Actor(持续效果,需要附着到Actor)。对于爆炸,我们用Static。
1 | // GCN_FireboltHit.h |
1 | // GCN_FireboltHit.cpp |
同样,编译后,在内容浏览器中基于此类创建蓝图BP_GCN_FireboltHit,并在蓝图中指定具体的粒子系统ExplosionParticle和声音ExplosionSound。
3 在投射物中触发GameplayCue
最后,修改火球投射物蓝图BP_FireboltProjectile。在其碰撞事件(OnHit)中,在造成伤害(通过ApplyGameplayEffectToTarget应用一个瞬时伤害GE)的同时,执行GameplayCue。
在蓝图中,可以使用Execute Gameplay Cue on Actor或Execute Gameplay Cue at Location节点。需要传递一个GameplayCueTag参数,这个标签需要和在BP_GCN_FireboltHit蓝图中设置的标签匹配(例如Cue.Firebolt.Impact)。
标签的管理是另一个话题,可以在项目设置中定义GameplayTag,然后在蓝图中通过Make Gameplay Tag节点来引用它。
当火球击中目标时,服务器会应用伤害GE,并广播一个“执行GameplayCue”的事件。所有客户端(包括施法者和旁观者)收到这个事件后,会根据标签找到对应的BP_GCN_FireboltHit蓝图,并在击中位置播放预设好的爆炸特效和音效。这样,一个完整的、带表现的火球术技能闭环就完成了。
测试、调试与下一步
完成以上所有步骤后,强烈建议在一个简单的场景中进行测试。确保角色蓝图正确挂载了ASC和AttributeSet,在BeginPlay时赋予了GA_Firebolt技能,并且输入按键已绑定。
按下按键,应该能看到角色播放施法动画,发射出一个火球投射物。当火球击中场景中的物体(或其他角色)时,应该播放爆炸特效和音效。同时,打开角色的属性界面(如果你做了UI),应该能看到魔法值被扣除,并且技能图标进入冷却状态。
如果遇到问题,UE5编辑器的**输出日志(Output Log) **。GAS会输出大量详细的日志信息,告诉技能激活失败的原因(CanActivateAbility失败)、属性修改的数值等。另外,可以打开 “~” 控制台,输入 showdebug abilitysystem 来在屏幕上显示当前选中角色的GAS状态,包括激活的技能、拥有的效果和当前的属性值,这对于调试至关重要。
走到这里,已经成功搭建了GAS最核心的流程。但这只是冰山一角。GAS的强大之处在于它的扩展性:
- 更复杂的技能:可以使用AbilityTask来实现蓄力、引导、通道等持续施法技能。
- 状态效果:利用GameplayEffect的Period(周期)属性,可以轻松实现“每秒钟掉血”的中毒效果,或者“持续10秒增加攻击力”的增益效果。
- 属性计算:通过GameplayEffectExecutionCalculation(GEEC)类,可以编写复杂的公式来计算伤害,比如(基础攻击力 + 力量*系数 - 目标防御力)。
- 预测(Prediction):为了让客户端操作更流畅,GAS支持预测某些动作(如移动、消耗资源),这需要更深入的理解。
建议你在掌握这个基础框架后,尝试着去实现一个治疗技能,或者一个给自己加攻击Buff的技能。GAS是一个框架,它提供了一套强大的工具和严谨的规则,但如何用这些工具搭建出你想象中的游戏世界,还需要不断地尝试和创造。




