UE 的 GAS 是什么#
GAS(Gameplay Ability System)是 UE 用于构建技能、属性、Buff/Debuff、状态控制和多人同步的一套玩法框架。它主要解决的不是“播放一个技能动画”,而是技能规模扩大以后出现的复杂问题:
1ASC负责统筹
2GA负责执行行为
3GE负责修改状态
4Attribute负责保存数值
5Tag负责描述和约束状态
6AbilityTask负责异步流程
7GameplayCue负责表现
一、GAS的核心组成#
1. Ability System Component:系统中枢#
UAbilitySystemComponent,简称 ASC,是Actor进入GAS体系的入口。
- 当前拥有的技能;
- 技能的授予、激活和移除;
- Attribute和AttributeSet;
- 当前生效的GameplayEffect;
- 当前拥有的GameplayTag;
- GameplayEvent;
- 技能网络复制和预测。
一般让Actor实现IAbilitySystemInterface,通过GetAbilitySystemComponent()返回ASC。ASC既可以放在Character上,也可以放在PlayerState上。将ASC放在PlayerState上,可以让属性、技能和长时间冷却在角色死亡、换Pawn后继续存在。(Epic Games Developers)
ASC放在哪里#
玩家死亡并重新生成Character,技能冷却不应该重置,ASC应该放在哪里?
通常回答:放在PlayerState,PlayerState作为长期Owner,当前Character作为技能实际操作的Avatar。
2. Gameplay Ability:一个可执行的能力#
UGameplayAbility,简称 GA,描述“角色要做什么”。
GA不只是一个函数。它可以跨越多帧执行,等待动画、输入、命中数据或GameplayEvent,并在结束或取消时统一清理。它支持成本、冷却、标签约束、网络执行策略和客户端预测。(Epic Games Developers)
一个Ability的基本生命周期#
1服务器授予Ability
2 ↓
3GiveAbility → FGameplayAbilitySpec
4 ↓
5TryActivateAbility
6 ↓
7CanActivateAbility
8 ↓
9ActivateAbility
10 ↓
11CommitAbility
12 ↓
13启动AbilityTask并等待动画/输入/事件
14 ↓
15造成效果或修改状态
16 ↓
17EndAbility / CancelAbility
GiveAbility通常只能由权威端执行,并返回FGameplayAbilitySpecHandle。TryActivateAbility会先检查能否激活,再真正调用激活逻辑;CommitAbility一般负责应用技能消耗和冷却;能力执行结束后必须调用EndAbility,否则GAS会继续认为技能处于激活状态,相关阻塞标签也可能一直存在。(Epic Games Developers)
CommitAbility为什么重要#
一般不要一进入ActivateAbility就无条件扣蓝、扣体力。
1ActivateAbility
2→ 检查目标或开始瞄准
3→ 确定技能确实可以执行
4→ CommitAbility
5→ 扣除资源并进入冷却
6→ 执行后续技能流程
如果CommitAbility失败,通常应立即结束Ability。
3. Attribute与AttributeSet:角色数值#
1Health
2MaxHealth
3Mana
4Stamina
5AttackPower
6Defense
7MoveSpeed
8CriticalRate
这些属性通常放在继承自UAttributeSet的类中。当前官方文档要求AttributeSet及其Attribute在原生C++中定义。(Epic Games Developers)
Base Value与Current Value#
FGameplayAttributeData包含两个重要值:
1基础移动速度:600
2减速Debuff:-30%
3Current MoveSpeed:420
减速结束后,Current恢复到600,而Base没有改变。AttributeSet将属性集中管理,并支持属性复制、临时修改和变化回调。(Epic Games Developers)
常见回调#
PreAttributeChange#
1void UMyAttributeSet::PreAttributeChange(
2 const FGameplayAttribute& Attribute,
3 float& NewValue)
4{
5 Super::PreAttributeChange(Attribute, NewValue);
6
7 if (Attribute == GetMoveSpeedAttribute())
8 {
9 NewValue = FMath::Clamp(NewValue, 0.0f, 1200.0f);
10 }
11}
PostGameplayEffectExecute#
Instant GameplayEffect完成修改后执行,适合:
官方也将PreAttributeChange定位为数值约束,将PostGameplayEffectExecute定位为效果执行后的最终处理和玩法反应。(Epic Games Developers)
4. Gameplay Effect:改变角色状态#
UGameplayEffect,简称 GE,负责描述“角色状态如何改变”。
GameplayEffect本身通常是不可变的数据资产;运行时真正携带等级、来源、目标、动态数值和上下文的是FGameplayEffectSpec。(Epic Games Developers)
GE的三种持续类型#
类型 | 用途 | 示例 |
Instant | 立即执行,不进入Active GE容器 | 伤害、治疗、永久加点 |
Has Duration | 持续一段时间 | 10秒加速、5秒眩晕 |
Infinite | 无限持续,直到主动移除 | 装备加成、被动状态 |
带持续时间的GE会进入ASC的Active Gameplay Effects Container;Instant GE执行后不会作为持续效果保存在其中。Periodic GE则会按设定周期重复执行。(Epic Games Developers)
Modifier、MMC与Execution Calculation#
Modifier#
1Health - 100
2AttackPower + 20
3MoveSpeed × 0.7
MMC#
UGameplayModMagnitudeCalculation用于计算一个Modifier的Magnitude。
1护盾值 = 技能等级 × 50 + 法术强度 × 0.6
它主要负责“算出一个数”,然后交给Modifier使用。(Epic Games Developers)
Execution Calculation#
UGameplayEffectExecutionCalculation适合复杂计算,并且可以一次输出多个属性修改。
1基础伤害
2→ 读取攻击者攻击力
3→ 读取目标防御力
4→ 计算暴击
5→ 计算元素抗性
6→ 计算最终Damage
7→ 同时产生生命削减、韧性削减和吸血
Execution可以读取来源和目标的属性快照,再向输出中添加多个Modifier。(Epic Games Developers)
MMC和Execution Calculation有什么区别?
MMC通常为一个Modifier计算Magnitude,更适合可复用的单值公式;Execution Calculation适合一次执行涉及来源属性、目标属性、多步判断和多个输出的复杂公式,例如伤害结算。
5. Gameplay Tag:GAS的状态语言#
1Ability.Attack.Light
2Ability.Attack.Heavy
3Ability.Movement.Dodge
4
5State.Attacking
6State.Stunned
7State.Dead
8State.Invincible
9
10Cooldown.Skill.Fireball
11Event.Melee.Hit
12GameplayCue.Hit.Fire
Tag不是普通字符串,也不仅是Enum。它们可以形成层级关系:
1State.CrowdControl.Stun
1State.CrowdControl
2State
GameplayTag可以用于描述对象类型、当前状态、事件和触发条件。(Epic Games Developers)
Tag在Ability中的典型用途#
1State.Stunned
1ActivationBlockedTags:
2 State.Stunned
3 State.Dead
1ActivationOwnedTags:
2 State.Attacking
1CancelAbilitiesWithTag:
2 Ability.Attack.Light
- 阻止其他技能;
- 取消正在执行的技能;
- 要求角色必须具有某状态;
- 要求角色不得具有某状态;
- 判断目标是否可被技能命中。(Epic Games Developers)
1if (!bDead && !bStunned && !bAttacking && !bClimbing && ...)
1ActivationBlockedTags:
2 State.Dead
3 State.Stunned
4 State.Climbing
6. Ability Task:跨帧异步流程#
GameplayAbility通常不依靠自己的Tick驱动流程,而是启动UAbilityTask。
AbilityTask可以跨越多帧,通过Delegate或蓝图输出引脚通知Ability,并会在所属Ability结束时最迟终止。(Epic Games Developers)
1ActivateAbility
2→ WaitInputRelease
3→ 玩家持续按住
4→ 计算蓄力时间
5→ 输入释放
6→ 播放攻击Montage
7→ 等待命中事件
8→ 应用伤害GE
9→ EndAbility
AbilityTask和普通异步任务的区别#
AbilityTask并不等同于“把工作放到其他CPU线程”。
7. Gameplay Cue:只负责表现#
GameplayCue需要使用以GameplayCue开头的Tag,例如:
1GameplayCue.Hit.Slash
2GameplayCue.Buff.Burning
GameplayCue主要是网络友好的外观表现机制,不应承载扣血、添加状态等关键玩法逻辑。官方明确指出Cue不使用可靠复制,因此关键玩法结果不能依赖Cue是否成功播放。(Epic Games Developers)
1GameplayEffect决定目标受到伤害
2GameplayCue负责播放受击火花和音效
二、用你的近战攻击项目理解GAS#
假设把你现在UE5 RPG项目里的近战攻击改成GAS,可以设计成下面这样。
1. 按下攻击键#
Enhanced Input不直接调用“扣血函数”,而是让ASC尝试激活:
1Ability.Attack.Light
2. GAS检查能否激活#
1角色是否死亡
2角色是否眩晕
3角色是否正在攀爬
4体力是否足够
5技能是否处于冷却
6当前是否允许进入下一段连击
这些条件主要由Tag、Cost GE、Cooldown GE和CanActivateAbility共同处理。
3. 激活攻击Ability#
1GA_LightAttack
2→ CommitAbility
3→ 应用体力消耗
4→ 应用攻击冷却
5→ 添加State.Attacking
6→ 播放Montage
4. 动画到达命中帧#
1Event.Melee.Trace.Begin
5. 检测到目标#
1GE_Damage
6. 目标结算伤害#
1攻击者AttackPower
2目标Defense
3技能倍率
4暴击率
5伤害类型
6目标抗性
目标AttributeSet在PostGameplayEffectExecute中:
1Health -= Damage
2→ Clamp Health
3→ Health <= 0时进入死亡流程
7. 播放表现#
1GameplayCue.Hit.Slash
8. 攻击完成或被打断#
1Montage完成
2→ EndAbility
3
4收到State.Stunned
5→ CancelAbility
6→ 停止Montage
7→ 清理Trace
8→ 移除State.Attacking
1输入
2→ ASC
3→ GameplayAbility
4→ AbilityTask播放动画
5→ GameplayEvent开启攻击检测
6→ TargetData
7→ GameplayEffectSpec
8→ Execution Calculation
9→ AttributeSet
10→ GameplayCue
11→ EndAbility
三、GAS的多人网络逻辑#
GAS并不是让客户端直接决定伤害,而是在服务器权威的基础上,提供本地预测来改善操作手感。
Local Predicted#
- Local Predicted;
- Local Only;
- Server Initiated;
- Server Only。(Epic Games Developers)
哪些技能适合Local Predicted#
哪些适合Server Only或Server Initiated#
需要注意:可预测的非Instant GE通常更容易在服务器拒绝时回滚,而伤害等Instant属性变化不能简单依赖同样的回滚方式。因此通常让客户端预测动作、动画和部分状态,最终伤害仍由服务器权威确认。(Epic Games Developers)
四、Ability的实例化策略#
GAS提供三种Ability Instancing Policy。
Non-Instanced#
Instanced Per Actor#
每个Actor持有一个Ability实例,多次执行重复使用。
Instanced Per Execution#
适合低频、复杂、可能并发执行的能力。(Epic Games Developers)
五、GAS最常见的错误#
1. 忘记EndAbility#
2. 在GameplayCue里写玩法逻辑#
3. 直接修改Health#
1Health -= Damage;
4. 所有状态都做成Attribute#
Health适合Attribute,但“眩晕”“正在攻击”“无敌”更适合GameplayTag。
1连续数值 → Attribute
2离散状态 → GameplayTag
3行为流程 → GameplayAbility
4数值变化 → GameplayEffect
5外观反馈 → GameplayCue
5. 在Ability中堆积所有伤害公式#
伤害公式应尽量放在可复用的MMC或Execution Calculation中,而不是每个攻击GA各写一次。
6. Ability取消时没有清理外部资源#
AbilityTask能够随Ability结束,但Ability之外手工创建的资源仍需要自己管理。
六、总结GAS:#
GAS以ASC为中枢,用GA组织行为流程,用GE修改Attribute和Tag,用AbilityTask处理跨帧时序,用GameplayCue分离表现,并通过服务器权威与本地预测支持多人游戏。
原文:GAS