ue GAS(持续更新)
前言
基本架构
介绍
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 | 一种层级标签系统,用于标记对象的状态、行为的分类,实现高效的逻辑判断和驱动。 |
| GameplayCue(GC) | 处理客户端表现,如特效、音效等 |
💡 核心概念详解
为了让你更好地理解和使用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的基本步骤
- 启用插件:在UE编辑器的“插件”管理器中,找到并启用 “Gameplay Abilities” 插件。
- 设置项目模块:在项目的
.Build.cs文件中添加"GameplayAbilities","GameplayTags","GameplayTasks"模块依赖。 - 创建ASC:让你的角色C++类继承
IAbilitySystemInterface接口,并在构造函数中创建UAbilitySystemComponent的实例。 - 定义属性:创建一个继承自
UAttributeSet的C++类,并在其中定义所需的属性(如Health、Mana)。 - 授予技能:在角色初始化时(如
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来实现
角色需要拥有GA后,才能使用GA。
GA的使用分为实例化和释放两个过程,前者主要是生成一个FGameplayAbilitySpec对象,并为一部分非公有(非静态)属性赋值,如当前GA的等级。后者操作的实际对象则为Spec。
可以把Spec理解为GA的实例,GE等其他类也有相似的概念。\
通常来说,使用GA时不用去考虑两个过程的区别,除非你需要在实例化Spec后,手动修改一些在GA类上定义好的属性再去手动释放。在GE篇会详细介绍,用于实现技能的冷却、消耗。
添加GA
如果不使用C++修改,只能通过GE去添加GA,非常不方便。
- 在角色类中创建一个数组,游戏启动时自动添加数组里的GA
1 | .h |
- 在角色蓝图中使用Give Ability函数手动添加Ability
AbilitySystemComponent->GiveAbility()方法在蓝图中无法使用,这边自己封装了一个GiveAbility().
这是一个将ASC中未暴露给蓝图的函数进行封装的例子,如果想在蓝图中使用其他的ASC函数可以进行参考。
1 | .h |
- 使用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,Added或Removed是本地的)。
网络预测
客户端使用技能,客户端和服务器都需要执行,而且很多结果需要服务器的权威验证。但事事都等待服务器验证,就会有网络延迟问题,操作体验不佳,为了避免延迟,GAS支持本地预测执行GA,和预测添加GE。把GA的NetExecutionPolicy属性设置为LocalPredicted,就能让GA支持网络预测执行。
可以本地预测的
- 激活GA
- Trigger Events
- 生效GE
- 生效GC
- 蒙太奇动画
本地不可以预测的
- GE移除
- GE的周期性操作
预测执行框架的重点是客户端与服务器不一致时,如何回滚客户端的操作。
架构设计
- ASC应该放在哪里?不同放置位置的优缺点是什么?
放在Character上:适用于简单AI、单人游戏,实现简单但角色重生后数据丢失
放在PlayerState上:适用于多人PvP/PvE,角色重生数据保留但需处理Owner/Avatar分离
最佳实践:
对于多人RPG,推荐将ASC放在PlayerState上(Owner),而Character作为Avatar.
这样即使 Character 被销毁重建(如死亡重生),属性和技能状态仍然保留
- GAS中的属性系统是如何工作的?BaseValue和CurrentValue有什么区别?
FGameplayAttributeData是GAS属性的基本存储单元,每个属性包含两个值:
- BaseValue(基础值):永久性修改作用于此,如升级加点、装备穿戴
- CurrentValue(当前值):临时修改作用于此,如Buff加成、临时减速
核心模块
| 模块 | 职责 | UE 实现载体 |
|---|---|---|
| 属性系统 | 定义生命值、攻击力等数值 | UAttributeSet |
| 技能系统 | 定义释放技能的逻辑流程 | UGameplayAbility |
| 效果系统 | 数值修改、状态施加 | UGameplayEffect |
| 标签系统 | 状态标识、条件过滤 | FGameplayTag |
| 命中检测 | 攻击碰撞判定 | Trace / Overlap |
| Buff系统 | 持续效果管理 | GE (Duration/Infinite) |
| 连招系统 | 输入缓冲、招式链接 | FSM + AnimMontage |
| AI系统 | 敌方行为决策 | BehaviorTree + EQS |
| 同步系统 | 多人战斗状态一致 | GAS Prediction |
架构图
1 | ┌──────────────────┐ |
业务结合
BUff叠加
| 叠加策略 | 行为 | 适用场景 |
|---|---|---|
| AggregateBySource | 同一来源只保留一个,不同来源可叠加 | 不同角色的同种 Buff |
| AggregateByTarget | 目标身上只保留一个 | 唯一性 Buff(如护盾) |
| Stack Count | 可叠加层数,增加效果强度 | 中毒层数、流血层数 |
| Overflow | 超过最大层数时触发额外效果 | 满层爆发 |
| Duration Refresh | 新叠加刷新持续时间 | 大多数 DoT 效果 |
命中检测
| 方式 | 原理 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|---|
| Sphere/Box Overlap | 在指定位置检测重叠Actor | 简单高效 | 精度较低 | AOE、范围技能 |
| Line Trace | 射线检测 | 精准 | 无法表达武器体积 | 射击、远程攻击 |
| Shape Trace | 沿路径做形状扫掠 | 平衡精度与性能 | 复杂度适中 | 近战武器 |
| Socket 插值 Trace | 两帧间Socket位置插值 | 帧率无关、最精准 | 实现复杂 | 高品质近战 |
1 | 帧 N: 武器Socket位置 A₁, B₁ (刀尖, 刀根) |
连击
1 | 玩家输入"攻击" |
打击感
1 | 命中瞬间 |
网络同步
GAS支持哪些网络复制模式?各自适用于什么场景?
- Full模式:适用于单人/简单AI,所有GE复制给所有客户端
- Mixed模式:适用于玩家角色,GE仅复制给拥有者,Tag和Cue复制给所有人
- Minimal模式:适用于AI角色,不复制GE,仅复制Tag和Cue
GAS如何支持客户端预测和状态回滚?
GAS支持联机游戏中的网络复制和预测机制,服务器上的技能逻辑可以广播到客户端上展示,客户端技能也可以在本地先执行,若服务器预测不通过,则可以在客户端上回滚操作
- GAS 可预测的内容:
- 技能激活
- 触发 GameplayEvent
- 应用 GameplayEffect(属性修改)
- 添加/移除 GameplayTag
- 播放 AnimMontage
- 移动(基于 CharacterMovementComponent)
- 不可预测的内容:
- GameplayEffect 的移除
- GameplayCue 的某些触发
回滚方式
| 预测的东西 | 回滚方式 |
|---|---|
| 属性变化(扣蓝、扣血) | GAS 内部维护了属性变化的记录,直接反向操作恢复原值 |
| GameplayEffect(CD、Buff) | 预测创建的 GE 被标记为“待确认”,拒绝后直接 Remove |
| GameplayTag | GE 被移除时,它授予的 Tag 自动跟着消失 |
| 蒙太奇动画 | 调用 StopMontage,混合回待机动画 |
| 特效/音效 | GameplayCue 层面处理,停止播放(但可能已经播了一部分,这是预测的代价) |
| 生成的 Actor(投射物) | 预测生成的 Actor 会被标记,拒绝后销毁 |
逻辑表现分离
| 逻辑层 | 表现层 |
|---|---|
| GameplayAbility | AnimMontage (通过 AbilityTask) |
| GameplayEffect | GameplayCue (粒子/音效/震动) |
| AttributeSet | UI Widget (血条/伤害数字) |
| GameplayTag | 动画状态机 (ABP 中读 Tag) |
Key
FPredictionKey
首先介绍PredictionKey概念,它是一个uint16的id,客户端每次预测执行GA,都会赋予一个自增的新Key。后面客户端向Server发送Active GA,会带上这个PredictionKey,服务器之后确认或拒绝这次GA的激活,也都用PredictionKey来标识。
下面是几个接口,注意其中的PredictionKey参数
1 | //Client->Server 请求激活GA |
生成新key
1 | void FPredictionKey::GenerateNewPredictionKey() |
Key的依赖关系
exp:
如果GA中产生了GameplayEvent,串联激活其他GA,预测过程会更复杂些。
例如开枪后立即自动接一个Melee攻击,打一套“军体拳”。
分析:
GA的Activate过程中,串行的激活了另一个GA,那么这两次激活都有自己的PredictionKey,而且后一次依赖前一次。
下面是PredictionKey的生成过程,Base就是前一个Key,最后的AddDependency会建立这种依赖。
1 | void FPredictionKey::GenerateDependentPredictionKey() |
优化
优化
| 优化项 | 说明 |
|---|---|
| Ability Batching | 多个技能激活/执行合并为一个 RPC |
| GameplayCue Batching | 多个 Cue 合并一次网络传输 |
| ASC Lazy Loading | AI 角色延迟初始化 ASC,进入战斗时才加载 |
| Minimal Replication | AI 使用 Minimal 复制模式 |
| 非实例化 Ability | 简单被动技能使用 NonInstanced |
碰撞优化
| 优化项 | 说明 |
|---|---|
| 碰撞通道分离 | 武器使用专用 Trace Channel |
| 空间分区 | 先用粗粒度检测筛选候选目标 |
| 对象池 | 投射物、特效使用对象池复用 |
| LOD 检测 | 远处战斗使用简化碰撞体 |
动画优化
| 优化项 | 说明 |
|---|---|
| Significance Manager | 根据距离/屏幕占比降低 Tick 频率 |
| URO (Update Rate Optimization) | 远处角色降低动画更新率 |
| Cue 裁剪 | 屏幕外/远距离 Cue 不执行 |
| 特效 LOD | 远距离使用简化粒子 |
参考
用Unity制作一个极具扩展性的顶视角射击游戏战斗系统 - 知乎
基于 Unreal Lyra 的 GAS 属性扩展和应用 - 知乎

