继前一篇 Significance 预算与布娃娃 / PhysicsControl 的冲突修复 之后,我们在角色基类上加了一层「离屏即 suspend PhysicsAsset / Collision」的优化(ApplyPhysicsVisibilitySuspension),通过缓存「是否处于战斗」状态把战斗中的敌人豁免,让 weapon trace / AOE 仍能命中离屏目标。
Gameplay Ability(GA)是 GAS 的核心,用来定义角色能做的各种行为——攻击、施法、用道具、跳跃。它是可重用的蓝图或 C++ 类,把一段游戏逻辑连同动画、音效、特效打包,并和 Gameplay Effect、Attribute、Cue 协同。
GA 解决三件事:
- 标准化技能实现——所有主动技能和被动效果走同一套框架,关键回调统一:
ActivateAbility激活、CommitAbility提交、CancelAbility取消、EndAbility结束。 - 解耦逻辑——技能逻辑从角色蓝图/C++ 里剥出来,单独管理、单独复用。
- 网络同步——内置复制,多人下的技能同步基本不用自己造轮子。
Gameplay Attribute 是 GAS 里存储角色数值的核心数据结构——生命、耐力、攻击力、载具速度,凡是描述拥有者特性的浮点数都走它。
每个 Attribute 都有两个值,分清它们是用好 GAS 的前提:
Gameplay Cue 是 GAS 里专门处理纯表现的部分——粒子、音效、震动这类不影响玩法的视听反馈。它和玩法逻辑解耦:玩法只负责"该播个什么 Cue 了",具体播什么、怎么播交给 Cue Notify。
连接二者的是 GameplayTag。Cue 通过标签和继承自 GameplayCueNotify 的处理器全局映射,相同标签就能触发对应的视听逻辑。
两种 Notify 类型
| Class | 常用事件 | 适用场景 |
|---|---|---|
| UGameplayCueNotify_Static | Execute | 一次性触发,比如打击命中 |
| AGameplayCueNotify_Actor | Add / Remove | 实例化、可随时间操作直到被删除,适合循环粒子/音效 |
Gameplay Debugger Tools(GDT)是 UE 的实时调试工具,在游戏运行时(PIE、Simulate In Editor、独立游戏)观察和分析行为数据。它以覆盖层直接画在视口上,支持网络游戏同步显示,调 AI 行为、GAS 技能、导航、感知这类复杂系统时很顺手。
Gameplay Effect(GE)是一个继承自 UGameplayEffect 的纯数据资产。它本身不写逻辑,而是一张"指令单":描述要改哪些属性、怎么改、改多久,再交给 AbilitySystemComponent(ASC)去读取和执行。
这篇用一个能跑起来的示例工程,把 GAS 接进项目、让它运转起来,再围绕一个突进(Dash)技能把 Ability、Effect、Attribute、Cue、UI 同步串一遍。后续几篇 GAS 专题都基于这个环境展开。
GAS 是什么
Gameplay Ability System(GAS)是 UE 里给角色(Actor)加和管“能力”的一套框架。这里的“能力”泛指角色能做的动作和交互——跳跃、攻击、施法、与环境交互。GAS 既帮你定义这些能力,也管它们的整个生命周期(启动、执行、结束),同时管能力相关的属性(生命、法力、攻击力),让属性的修改安全、统一、可追踪。
GAS 把游戏状态管得很严(属性、冷却、技能判定大多服务器权威),UI 要把这些状态画出来,核心就一句话:UI 是观察者,不是查询者。让 UI 监听数据变化事件去刷新,而不是每帧主动去问。这样玩法层和表现层能各自独立迭代,互不打扰。
三条原则贯穿始终:
- 数据驱动、解耦——UI 监听"生命值变化"事件刷血条,玩法层改生命值的计算公式时根本不用管 UI。
- 事件驱动——用 GAS 内置的委托和事件实时推送状态变更。比每帧
Tick轮询省得多,只在真有变化时才触发。 - 权威性——关键状态由服务器管,UI 显示的数据必须源自或同步于权威数据源,否则多人下会出现各客户端看到的不一致。
Epic 自带的 GameplayAbilities 插件给了我们 ASC / Ability / Effect / Cue 这套抽象,但当项目规模膨胀到上百个能力、几百个攻击资产、上千个 GameplayTag 时,光靠原生类是兜不住的——会到处出现继承爆炸、配置散落、能力间互相硬引用。
这篇笔记整理一个真实 ARPG 项目里 GAS 的三层架构,以及围绕它沉淀的数据资产体系,供搭建中大型战斗系统时参考。
一、三层结构
把 GAS 切成自顶向下三层,每一层只关心自己的事:
| 层次 | 来源 | 职责 |
|---|---|---|
| Epic 原生层 | Engine/Plugins/GameplayAbilities |
UGameplayAbility、UAbilitySystemComponent、UGameplayEffect、FGameplayTag 等核心类型 |
| 内部框架层 | 内部公共插件 | 在原生类上扩展激活流程、标签关系、属性事件等通用能力,跨项目复用 |
| 项目层 | Source/<Game>/GAS |
项目专属实现:所有属性集、能力派生类、效果计算 |
ARPG 战斗里有一种很常见的"群战手感"问题:一刀劈到第一排敌人时,玩家会期待后面那一排也吃到一点伤害或趔趄,否则总感觉刀风没穿透。这篇笔记整理一个数据驱动的"攻击传递"机制 TDD,把它从需求、设计、实现一路记下来。
1. 概述
攻击传递:当一发近战攻击直接命中敌人时,会在每个被命中敌人沿 Player→受击者方向的前方生成一个盒形检测区域(沿该方向定向,尺寸取自被命中敌人的胶囊体并乘以可配缩放系数);处于该区域内、但未被玩家直接命中的敌人,也会受到一份与直接命中完全一致的伤害与趔趄效果(复用本攻击自身的配置)。