文章目录
前言
深入了解 Ability System(技能系统) 的实现原理,就从底层结构、执行流程、网络同步,到触发机制逐层拆解。这个系统是 GAS(Gameplay Ability System) 的核心,用于管理技能的激活、执行、冷却、条件判断、资源消耗等一整套流程。
一、Ability System 的核心组成
模块 | 说明 | 关键类 |
---|---|---|
技能对象 | 描述技能逻辑和行为 | UGameplayAbility |
技能组件 | 技能容器和调度器 | UAbilitySystemComponent (ASC) |
技能上下文 | 封装调用信息 | FGameplayAbilitySpec, FGameplayAbilityActorInfo |
技能任务 | 蓝图中组合行为 | UAbilityTask |
技能标签 | 控制是否可激活/中断等 | FGameplayTag, FGameplayTagContainer |
二、UGameplayAbility:技能定义类
每一个技能都继承自 UGameplayAbility 类,你可以在其中定义:
技能类型(Instant / Duration / Channeling)
激活条件
技能行为(动画、GE 应用、移动等)
生命周期关键函数:
virtual void ActivateAbility(const FGameplayAbilitySpecHandle Handle,
const FGameplayAbilityActorInfo* ActorInfo,
const FGameplayAbilityActivationInfo ActivationInfo,
const FGameplayEventData* TriggerEventData) override;
virtual void EndAbility(...) override;
virtual void CancelAbility(...) override;
三、技能的注册与初始化机制
技能本身并不自动存在于角色身上,只有注册到 AbilitySystemComponent(ASC)中,才能使用。
添加技能流程:
FGameplayAbilitySpec Spec = FGameplayAbilitySpec(AbilityClass, Level, InputID);
ASC->GiveAbility(Spec);
ASC->InitAbilityActorInfo(OwnerActor, AvatarActor);
- 每个技能对应一个 FGameplayAbilitySpec
- ASC 会创建该技能类的实例,绑定输入等
四、技能激活执行流程(详细调用链)
激活流程概览(通过蓝图 or 代码):
↓ 玩家按键(Input)
↓ ASC 调用 TryActivateAbility()
↓ 检查:激活条件(如 Tag、资源)
↓ 调用 Ability->ActivateAbility()
↓ AbilityTask 执行实际行为
↓ ApplyGE、WaitTarget、WaitGameplayEvent 等
↓ EndAbility() or CancelAbility()
五、FGameplayAbilitySpec:技能运行体
它记录每个技能的运行状态,包括:
struct FGameplayAbilitySpec {
UGameplayAbility* Ability; // 技能对象
int32 Level;
bool bIsActive;
FGameplayAbilityActivationInfo ActivationInfo;
FGameplayAbilitySpecHandle Handle;
TArray<UGameplayAbility*> ReplicatedInstances; // 网络同步用
};
一个技能可以有多个激活实例(如 DOT 技能多段激活)
六、技能输入绑定与触发原理
在 GAS 中,技能并不会直接响应输入,而是通过 InputID 实现:
FGameplayAbilitySpec Spec(MyAbility, 1, InputID);
ASC->GiveAbility(Spec);
然后再调用:
ASC->AbilityLocalInputPressed(InputID);
ASC->TryActivateAbilityByClass(MyAbilityClass);
或者你可以使用 Enhanced Input 系统绑定并传递到 ASC。
七、冷却 & 消耗机制
GAS 并不会自动实现冷却或消耗,但它提供了强大的数据驱动方式支持这两者:
方法一:使用 GE 管理冷却时间
Ability->CooldownGameplayEffectClass = UMyCooldownGE;
这个 GE 会:
- 授予角色 Cooldown.X 标签
- 设置持续时间(冷却时间)
- 在标签存在期间,禁止技能再次激活
方法二:使用 GE 管理消耗(蓝、体力)
Ability->CostGameplayEffectClass = UMyCostGE;
GE 的 Modifier 会减少 Mana、Stamina 属性
八、技能任务(Ability Task)机制
在 Blueprint 中你通过 Ability Task 来拼接技能逻辑,如:
WaitTargetData
↓
ApplyGameplayEffectToTarget
↓
WaitGameplayEvent
↓
EndAbility
任务类都继承自 UAbilityTask,例如:
UAbilityTask_WaitGameplayEvent
UAbilityTask_WaitDelay
UAbilityTask_ApplyRootMotion
你也可以自定义 Task,实现定制的技能行为流程。
九、网络同步原理
GAS 是高度权威服务器驱动,技能同步由服务器控制,客户端只能请求。
流程概览:
阶段 | 处理方式 |
---|---|
激活请求 | 客户端调用 ServerTryActivateAbility() |
技能执行 | 服务端执行 ActivateAbility(),广播 GE、动画等 |
结果同步 | ASC 同步 GE、属性变化、状态标签等到客户端 |
任务通知 | AbilityTask 自动使用 RPC 或事件广播通知客户端完成状态 |
例如,客户端看到技能动画,是服务器同步结果,而非本地执行。
十、技能中断与多技能管理机制
GAS 支持多技能并发、互斥、可打断机制:
技能互斥机制:
ActivationBlockedTags = Status.Stunned
CancelAbilitiesWithTag = Ability.Magic
中断机制:
Ability->EndAbility(CurrentSpecHandle, ActorInfo, ActivationInfo, true, false);
当 GE 加上一个如 Status.Stunned 的标签时,系统会自动取消与之冲突的技能。
十一、技能条件控制:标签、资源、状态
GAS 的技能激活控制非常精细化:
类型 | 控制手段 |
---|---|
状态阻断 | ActivationBlockedTags |
状态需求 | ActivationRequiredTags |
属性需求 | 在 CheckCost() 中判断属性值(如蓝是否足够) |
自定义逻辑 | 重写 CanActivateAbility() 进行复杂条件 |
十二、总结:Ability System 的核心价值
模块 | 功能 | 优点 |
---|---|---|
UGameplayAbility | 技能逻辑定义 | 支持蓝图 + C++ |
FGameplayAbilitySpec | 技能状态跟踪 | 可动态添加、修改等级 |
ASC | 技能执行入口 | 支持网络同步、GE 应用 |
AbilityTask | 技能逻辑拼装 | 像写脚本一样设计技能 |
GE + Tag | 数据驱动限制条件 | 易维护、组合灵活 |
示例:完整技能流程(如“火球术”)
- 玩家按下 Q → 调用 ASC->TryActivateAbility
- 系统检查:是否沉默?是否在冷却?
- 激活后播放动画 → 发射子弹
- 命中目标 → ApplyGameplayEffectToTarget(造成伤害)
- 给自己添加 Cooldown.Fireball GE(冷却)
- 技能生命周期结束