03-GAS核心对象与职责边界

3071 字
15 分钟
03-GAS核心对象与职责边界

第 3 章:GAS 核心对象与职责边界#

3.1 问题导入#

第一次接触 GAS,最直观的感受往往是:一个火球术为什么要拆出这么多对象?

只看单机原型,它确实可以写成一段连续逻辑:

检查并扣除 30 Mana
进入 2 秒冷却
命中后造成 120 点直接伤害
附加持续 5 秒、每 1 秒结算一次的 Burning
播放施法、命中和燃烧表现

问题在于,这些逻辑并不共享同一种生命周期:

  • Mana 和 Health 是角色长期存在的数值;
  • 冷却与 Burning 要在 Ability 结束后继续生效;
  • 一次施法的目标、等待和取消原因只属于本次执行;
  • 命中是一个瞬时消息,燃烧却是一种持续状态;
  • 粒子和音效可以播放失败,但不能改变服务器结算。

3.2 AbilitySystemComponent#

AbilitySystemComponent,简称 ASC,是某个 Actor 接入 GAS 的核心入口。

ASC 通常负责关联或管理:

已授予的 Ability Spec
AttributeSet
Active Gameplay Effect
Owned Gameplay Tags
正在执行的 Ability 与 Task
输入、事件、确认和取消的路由
能力系统相关的网络状态

这些状态大多不会随着一次施法结束而消失。火球术结束后,Mana 的新值仍要保留,冷却可能还没结束,目标身上的 Burning 也在继续结算。因此,ASC 的生命周期通常跟随角色,而不是某个 Ability Instance。

外部系统也应通过 ASC 进入能力系统:

  • 输入或 AI 提交“尝试激活某个能力”的意图;
  • Ability 查询属性、标签和已授予信息;
  • Effect 进入目标的效果与属性生命周期;
  • Event 被路由给 Ability 或 Task;
  • UI 观察属性、冷却和状态,而不必读取 Ability 内部变量。

3.2.1 Owner Actor 与 Avatar Actor#

ASC 还区分两个重要角色:

  • Owner Actor
  • Avatar Actor

普通敌人的 Owner 与 Avatar 可以是同一个 Actor。玩家角色则可能把持久能力状态放在 PlayerState 一类的身份对象上,把当前 Pawn 作为 Avatar。这样角色死亡、重生或换形态时,身体可以替换,能力、属性和冷却是否保留则由明确规则决定。

3.2.2 ASC 的边界#

ASC 是协调中心。但移动、背包、任务、相机等系统不应仅因为和角色有关就被塞进 ASC。

同样,一次施法的目标点、投射物引用和动画等待结果也不适合长期放在 ASC 中。这些状态属于 Ability Instance 或 Ability Task;否则多个 Ability 并发时很容易互相覆盖。

3.3 GameplayAbility#

GameplayAbility 描述一个能力从激活到结束如何推进。火球术、闪避、治疗、蓄力攻击、受击反应和被动触发,都可以用 Ability 表达。

Ability 适合负责:

  1. 响应激活;
  2. 检查流程是否可以继续;
  3. 决定何时提交 Cost 和 Cooldown;
  4. 创建 Task,等待动画、目标或命中;
  5. 请求应用伤害、治疗、Buff 或 Debuff Effect;
  6. 处理成功、失败、取消和打断;
  7. 清理本次执行并明确结束。

3.3.1 Definition、Spec 与 Instance#

层次典型内容生命周期
Ability Definition默认配置、标签要求、Cost、Cooldown、流程入口长期复用
Ability Spec来源、等级、运行时标识、输入关系从授予到撤销
Ability Instance目标、Task、Commit 状态、取消原因单次激活

同一个火球术 Definition 可以被多个角色共享,但每个角色在自己的 ASC 上拥有独立 Spec。真正施法时,本次目标、投射物和等待状态则属于 Instance。

UE GAS 还提供不同的 Ability 实例化策略。它们会影响执行状态具体存放在哪里,但不会改变这三个语义层次。

3.3.2 Ability 的协作边界#

Ability 从 ASC 获取上下文,通过 Effect 提交规则变化,通过 Task 等待异步结果,并在适当阶段触发表现语义。它不应直接维护长期 Buff Timer,也不应把粒子资源和数值结算写进同一条执行链。

Ability 最重要的生命周期要求是:所有路径都必须结束。 正常完成、条件失败、外部取消和网络拒绝,都要进入统一的结束与清理流程。

3.4 AttributeSet#

AttributeSet 用来组织可被规则读取和修改的数值,例如:

Health
Mana
Stamina
AttackPower
Armor
MoveSpeed

这些数值不是某个 Ability 的私有变量。Mana 可能同时被技能检查、Cost Effect 扣除、回复效果增加、UI 显示,并接受服务器校正。把它们放进统一的 Attribute 体系,才能保证所有系统面对的是同一份规则事实。

理解 Attribute 时,可以先建立一个简化模型:

概念含义
Base Value成长、初始化等形成的基础值
Modifier装备、Buff、Debuff 等来源提供的修改
Current Value当前可供规则读取和结算的结果

具体项目可以采用不同计算公式,但加法、乘法、覆盖、钳制和派生属性的顺序必须统一,不能由每个 Ability 自行决定。

3.4.1 AttributeSet 的边界#

Ability 可以读取 Mana 判断是否满足条件,正式扣除通常应通过 Cost Effect 提交;伤害也应通过 Damage Effect 进入目标的属性结算,而不是直接执行 Health -= damage

离散状态不适合硬塞成 0/1 Attribute。State.StunnedState.Dead 这类通常更适合 Gameplay Tag。

3.5 GameplayEffect#

GameplayEffect 描述某个来源如何改变目标的数值或状态,以及这种变化持续多久。

Ability 决定何时、向谁应用规则;Effect 描述规则本身。

3.5.1 Effect Definition 与 Active Effect#

Effect 同样需要区分定义和运行时状态:

  • Effect Definition 描述 Modifier、持续时间、周期、标签和计算规则;
  • Active Gameplay Effect 表示某个持续效果已经被应用到目标,并正在运行。

Active Effect 通常需要跟踪来源、目标、开始时间、剩余时间、下一次周期结算、叠加状态和移除条件。Instant Effect 完成结算后通常无需继续存在;Duration 或 Infinite Effect 则必须被目标 ASC 跟踪。

3.5.2 生命周期与周期#

Effect 的寿命和执行频率是两个维度:

类型语义常见用途
Instant应用时结算一次,然后结束Cost、直接伤害、即时治疗
Duration在有限时间内保持有效冷却、限时 Buff、Burning
Infinite没有自然到期点,需要显式移除装备加成、姿态、常驻被动
Periodic在有效期间按固定间隔执行持续伤害、持续恢复

Periodic 不是与 Duration、Infinite 并列的第四种寿命。一个 Duration Effect 可以周期执行,一个 Infinite Effect 也可以周期执行。配置持续伤害时,至少要说明:

持续多久
多久结算一次
首次结算在应用时还是首个间隔后
刷新、叠加和移除如何处理

3.5.3 Granted Tags 与来源#

持续 Effect 可以在生效期间向目标贡献 Gameplay Tag。例如:

Cooldown Effect 有效 -> 贡献 Cooldown.Fireball
Burning Effect 有效 -> 贡献 Effect.Burning

Effect 结束时,系统撤销的是该来源对标签的贡献,而不是无条件删除标签。如果两个独立 Effect 都贡献 Effect.Burning,移除其中一个后,只要另一个仍有效,目标就仍然拥有该标签。

这也是 Active Effect 必须记录来源和生命周期的原因。若 Ability 自己开 Timer、手动添加和删除标签,叠加、净化、死亡、重连和网络同步都会失去统一入口。

3.5.4 GameplayEffect 的边界#

Effect 负责规则变化,不负责组织整条技能流程。它可以修改 Attribute、贡献 Tag、触发对应 Cue,但不应承担瞄准、等待动画和处理玩家输入。

Infinite Effect 也不是“不想设计结束条件”时的默认选项。它没有自然到期点,因此更需要明确由谁、在什么条件下移除。

3.6 GameplayTag:跨系统共享的状态语言#

GameplayTag 是结构化语义标识,用来描述离散状态、规则分类和事件类型:

State.Dead
State.Stunned
State.Casting
Cooldown.Fireball
Effect.Burning
Event.Projectile.Hit
Cue.Fireball.Impact

Tag 的价值在于让 Ability、Effect、输入、AI、UI 和表现层围绕同一种语义协作。例如,“死亡或眩晕时不能施法”可以写成统一的标签查询,而不必让每个技能分别读取多个布尔变量。

单个 Tag 本身没有计时器。

因此,标签持续多久取决于来源持续多久。临时 Tag 必须有明确的添加者和撤销者。

3.6.1 GameplayTag 的边界#

Tag 适合表达分类和离散状态,不适合携带可计算数值。Damage.120Stack.3 会把数据硬编码进名称;这些值应放进 Attribute、Effect 参数或 Event Payload。

Tag 也不等同于 Event:

前者可以被持续查询,后者只描述某个瞬间发生的事情。

3.7 GameplayEvent#

GameplayEvent 用来把外部发生的能力语义送入 GAS,而不让发送者直接调用某个 Ability 的内部函数。

常见事件包括:

Event.Projectile.Hit
Event.Animation.CastPoint
Event.Damage.Taken
Event.Target.Confirmed

投射物命中后,可以发送一个包含目标、命中点和来源的 Event。投射物系统只负责报告事实,不需要知道火球术执行到了哪一步,也不应直接修改目标 Health。

Event 的生命周期很短:创建、路由、消费,然后结束。它可以携带 Payload,但不能承担持续状态。如果需要在稍后查询“目标是否仍在燃烧”,应读取 Tag 或 Active Effect,而不是寻找最后一次命中事件。

3.7.1 Event 的边界#

Event 只是信号,不自动等于权威结果。客户端上报“投射物命中”后,服务器仍需要验证目标、距离、时序和执行上下文,才能决定是否应用伤害 Effect。

Event Bus 也不应变成全局任意消息中心。事件需要有稳定命名、明确接收上下文和受约束的 Payload,否则来源、权威和消费关系会逐渐失控。

3.8 AbilityTask#

AbilityTask 用来封装 Ability 执行中的异步等待,例如:

等待动画到达 Cast Point
等待玩家确认目标
等待投射物命中
等待服务器确认或拒绝
等待收招结束

Task 的关键是它明确属于某个 Ability Instance。

Task 的生命周期不能长于创建它的 Ability Instance。Ability 结束或被取消后,尚未完成的 Task 必须一起终止,避免几秒后继续应用伤害或播放表现。

3.9 GameplayCue:规则层与表现层的协议#

GameplayCue 把已经确认的规则语义映射为动画、VFX、SFX、镜头和 UI 表现。

火球术可以使用不同 Cue 表达不同阶段:

Cue.Fireball.Cast
Cue.Fireball.Launch
Cue.Fireball.Impact
Cue.Burning.Loop
Cue.Burning.Remove

Cue 可以是瞬时的,也可以跟随持续规则状态。

Cue 保存的是表现状态,而不是权威战斗状态。粒子被裁剪、音效播放失败、服务器不创建表现对象,都不应改变伤害和 Burning 的结算。

3.9.1 为什么不直接播放粒子#

Ability 直接加载和播放粒子,会同时绑定规则流程与具体资源。这样做会带来几个问题:

  • 服务器代码可能接触只属于客户端的表现对象;
  • 预测被拒绝时缺少统一撤销入口;
  • 持续表现与 Effect 生命周期容易不同步;
  • 美术替换 VFX、SFX 或镜头时需要修改规则代码。

Cue 先建立稳定的表现语义,再由客户端表现层决定具体资源和降级策略。

Cue 不能修改 Health、判定命中或决定 Effect 是否生效。否则表现是否播放会反过来影响规则结果,服务器权威也会失去可靠边界。

3.10 核心对象关系#

把前面的对象放在一起,可以得到下面这张关系图:

Owner Actor
|
| 状态归属
v
AbilitySystemComponent <---- Avatar Actor
| 当前世界载体
|
+-- Ability Spec -------> Ability Definition
| |
| +-- 激活 --------> Ability Instance
| |
| +-- 创建 AbilityTask
| +-- 接收 GameplayEvent
| +-- 应用 GameplayEffect
|
+-- AttributeSet <------ GameplayEffect 修改数值
|
+-- Active GameplayEffect
| |
| +-- 跟踪持续时间、周期和来源
| +-- 贡献 Owned Gameplay Tags
| +-- 触发或维持 GameplayCue
|
+-- Owned Gameplay Tags
|
+-- GameplayCue --------> 动画、VFX、SFX、UI、镜头
03-GAS核心对象与职责边界
https://blog.rouming-fei.top/posts/03-gas-core-objects-and-responsibility-boundaries/
作者
废江流
发布于
2026-08-04
许可协议
CC BY-NC-SA 4.0

评论区

Profile Image of the Author
废江流
提灯寻影,灯到影灭。
分类
标签
站点统计
文章
15
分类
4
标签
18
总字数
37,248
运行时长
0
最后活动
0 天前

文章目录