UNREAL ENGINE

虚幻 GAS 手册

Gameplay Ability System 的概念、接入顺序和踩坑,收成一页。中文按引擎里的事实来写,英文是同一事实的技术英语,两边都能单独读。类名不翻译。

这页收了什么

What this page keeps

网上和虚幻 Gameplay Ability System(GAS)有关的帖子没有边界:官方文档、引擎源码、Lyra、tranek 的社区手册、中文译文、直播笔记、付费插件说明会互相复述。把它们贴成一堵墙,读不完,也会把 4.27 的写法当成 5.6 的事实。这页只留反复出现、而且能对上插件源码的部分,写成一份能读完的手册。原文放在页尾,点开再核对。

Posts about Unreal's Gameplay Ability System have no edge. Official docs, the plugin source, Lyra, tranek's community manual, Chinese translations, livestream notes, and a paid plugin all retell each other. Pasting them into one wall does not make a guide, and it treats a 4.27 habit as a 5.6 fact. This page keeps the parts that show up everywhere and still match the plugin, written so you can finish them. The originals are at the bottom.

类名、函数名、标签保持英文,编辑器和源码里就是这些名字。英文段按同一件事实另写一遍,可以单独读,不是中文的逐句回译。本站和 Epic 无关,也不保证你手头那个引擎小版本里每个默认值都没改过。最后以本机 Engine/Plugins/Runtime/GameplayAbilities 为准。

Class names, functions, and tags stay in English, because that is what the editor and the source use. The English paragraphs are written as English about the same facts, not line-by-line from the Chinese, so either column can stand alone. This site is not affiliated with Epic. A hotfix can still move a default. When a sentence and your engine disagree, the copy under Engine/Plugins/Runtime/GameplayAbilities wins.

什么时候值得上 GAS

When GAS is the right tool

GAS 是 Epic 随引擎带上的插件,在《Paragon》和《堡垒之夜》里用过,Lyra 示例是现在能看到的官方接法。它解决的是一类具体问题:很多动作要共享同一套规则——能不能放、花什么、冷却多久、给谁挂上眩晕、等级一变数值怎么变——并且在联机里让服务器说了算,客户端可以先动,被拒绝再收回。

GAS ships with the engine. Epic used it in Paragon and Fortnite, and Lyra is the current sample of how they wire it. It solves a specific problem: many actions have to share one set of rules. Can it run, what does it spend, how long is it down, who is stunned, what happens when the level changes. On a server, that server gets the last word. The client may start early and has to take it back if the server says no.

单机、动作就三五个、数值写死在角色蓝图上,硬上 GAS 只是多一层你还用不到的复制和预测。移动、动画蓝图、AI 行为树也不该搬进技能类里。GAS 决定动作合不合法、改了什么数、别的机器该信哪一份;角色怎么走,仍是 CharacterMovement 的事。

A single-player pawn with a handful of actions and numbers baked into the character Blueprint does not need this. You would be paying for replication and prediction you are not using. Movement, animation Blueprints, and behavior trees do not belong inside an ability class. GAS decides whether an action is legal, which numbers changed, and which result the other machines may believe. How the pawn walks is still CharacterMovement.

先把插件接上

Turn the plugin on for real

编辑器里启用 Gameplay Abilities。然后在模块的 Build.cs 里把 GameplayAbilities、GameplayTags、GameplayTasks 加进依赖。只勾插件、不改 Build.cs,C++ 会在链接期找不到符号。标签系统是独立模块,GAS 用它,但没有 GAS 的项目也可以只用标签。

Enable the Gameplay Abilities plugin in the editor, then add GameplayAbilities, GameplayTags, and GameplayTasks to your module's Build.cs. The checkbox alone does not put those modules on the link line, and the C++ build will fail looking for symbols. Gameplay Tags are their own module. GAS depends on them. A project can use tags without ever enabling GAS.

从 4.24 到 5.2,要用 Target Data(技能把「打中了谁、打在哪一点」交给服务器确认)之前,必须自己调用一次 UAbilitySystemGlobals::Get().InitGlobalData()。tranek 的示例放在 Asset Manager 的 StartInitialLoading。5.3 起引擎会自己做。旧教程里的那一行在 5.3 及以后是多余的,删掉不会少功能。

From 4.24 through 5.2, Target Data — the payload an ability sends so the server can confirm who was hit and where — stays inert until something calls UAbilitySystemGlobals::Get().InitGlobalData() once. The tranek sample does it from the asset manager's StartInitialLoading. Starting in 5.3 the engine does this itself. On 5.3 and later that line in older tutorials is redundant, and deleting it drops nothing.

几块东西怎么咬合

How the pieces lock

一次普攻走完,链路通常是这样:输入变成「要放哪条技能」,技能组件检查标签、消耗和冷却,技能自己跑流程,在该结算的时刻提交一个效果,效果改属性或挂上标签,表现通知负责火花和音效。标签贯穿条件。属性集保管数字。技能组件是这些对象进出的那一扇门。

A basic attack runs a short chain. Input becomes "activate this ability." The ability system component checks tags, cost, and cooldown. The ability runs its procedure and, at the moment the hit counts, commits an effect. The effect changes an attribute or grants a tag. A gameplay cue plays the spark and the sound. Tags are the condition language. The attribute set holds the numbers. The component is the door every one of those objects goes through.

效果是数据包,不是流程图。设计师在蓝图子类里调持续时间、修饰符和标签。公式、追踪、动画等待写在技能、执行计算(Execution)或修饰幅度计算(MMC)里,不要写进效果本身。表现通知只负责给玩家看和听。在通知里改血,那次修改不会按 GAS 的规则复制,也不会在预测被拒绝时干净地收回。

An effect is a data asset, not a flowchart. Designers tune duration, modifiers, and tags on a Blueprint child. Formulas, traces, and "wait for the montage" belong on the ability, on an execution calculation, or on a modifier magnitude calculation. They do not belong on the effect. A cue is presentation. If a cue writes health, that write is outside GAS replication, and a rejected prediction will not undo it cleanly.

技能组件

Ability System Component

UAbilitySystemComponent 是枢纽。凡是要放技能、持有属性、吃效果的 Actor,都得有一个。它在 C++ 构造函数里创建,并设成复制。只在蓝图里 Add Component,复制和初始化很容易缺一条路径,社区手册把这件事写成必须在 C++ 里做。可以子类,Lyra 就子类了;不子类也能用。

UAbilitySystemComponent is the hub. Any actor that activates abilities, owns attributes, or receives effects needs one. Construct it in C++ and mark it replicated. Adding it only from a Blueprint component list is a reliable way to miss a replication or init path. The community manual treats the C++ constructor as mandatory. Subclassing is optional. Lyra subclasses it. You do not have to.

让角色或 PlayerState 实现 IAbilitySystemInterface,返回这块组件。别的系统用 UAbilitySystemGlobals::GetAbilitySystemComponentFromActor 找它时,会先走接口,找不到才在组件列表里搜。授予技能用 GiveAbility,激活用 TryActivateAbility,取消用 CancelAbility,把一份效果规格作用到目标上用 ApplyGameplayEffectSpecToTarget。这些授予和应用,权威端在服务器。客户端那份是复制来的,或者是带预测键的头马。

Implement IAbilitySystemInterface on the character or the player state and return the component. UAbilitySystemGlobals::GetAbilitySystemComponentFromActor checks that interface before it searches the component list. GiveAbility grants, TryActivateAbility starts, CancelAbility stops, ApplyGameplayEffectSpecToTarget applies a spec. Granting and authoritative application happen on the server. What the client has was replicated, or it is a head start carrying a prediction key.

持有者和化身:组件放哪

Owner, avatar, and where the component lives

组件有两个 Actor 指针。OwnerActor 是这块组件的主人。AvatarActor 是此刻站在世界上、拿来播动画、做碰撞的那具身体。两者可以是同一个角色。InitAbilityActorInfo 要在服务器和客户端都调用,只在服务器调,客户端的技能和界面会对着一份没初始化的组件。

The component keeps two actor pointers. OwnerActor owns it. AvatarActor is the body in the world right now, the one that plays montages and traces. They may be the same character. Call InitAbilityActorInfo on the server and on the client. Server-only init leaves the client talking to a component that was never introduced to its pawn.

组件放在角色上,人死了、Pawn 毁了,冷却和属性一起走。小兵、不需要跨命继承状态的单位,这样最省事。组件放在 PlayerState 上,换身体之后冷却、Buff 和属性还在,因为 PlayerState 还在。Lyra 和 tranek 示例里的英雄走这条路。代价是:每次重新 Possess 都要再 Init 一次,把化身从尸体改到新身体上。客户端要等 PlayerState 复制到了再 Init,所以放在 Pawn 的 OnRep_PlayerState,服务器放在 PossessedBy。

Put the component on the character and it dies with the pawn. Cooldowns and attributes go with it. That is the cheap setup for minions and for anything that should not carry state across a life. Put it on the player state and cooldowns, buffs, and attributes survive a new body, because the player state does. Lyra and the heroes in the tranek sample do this. The cost: every new possession has to call Init again, or the avatar pointer still names the corpse. On the client, wait until the player state has replicated. That is OnRep_PlayerState on the pawn. On the server, PossessedBy.

PlayerState 默认的网络更新频率很低,属性和标签会显得慢半拍。把 NetUpdateFrequency 拉高。Lyra 还会打开自适应更新频率。这件事和 GAS 的逻辑无关,是 Actor 复制通道的节流,但组件若挂在 PlayerState 上,你就会撞上它。

A player state's default net update frequency is very low, so attribute and tag changes look late. Raise NetUpdateFrequency. Lyra also turns on adaptive update frequency. That throttle is not a GAS rule. It is the actor replication channel. You hit it the moment the component lives on the player state.

效果怎么复制

How effects replicate

复制模式管的是游戏效果、标签和表现,不是属性。属性由属性集自己复制。模式有三档。Full:每个效果的完整信息复制给所有人,单机或 Actor 很少时用。Mixed:拥有者(以及自主代理)拿到完整效果,其他人只拿到标签和表现。玩家控制的联机角色用这档。Minimal:效果本身不复制给任何人,大家只看到标签和表现。没有所属客户端的 AI 用这档。

The replication mode covers gameplay effects, tags, and cues. Attributes replicate from the attribute set, not from this mode. Full sends every effect, in full, to every client. Use it for single player or for very few actors. Mixed sends the full effect to the owner and to autonomous proxies, and sends only tags and cues to everyone else. That is the mode for a player-controlled pawn in multiplayer. Minimal never replicates the effect itself. Everyone still sees tags and cues. Use it for AI that has no owning client.

Minimal 不能用在「有所属连接」的组件上,引擎注释写的是这种组件改用 Mixed。原因很具体:冷却剩余时间、Buff 列表要读本机那份活跃效果。Minimal 不把效果复制给拥有者,本机的冷却条就没有数据来源。模拟代理(你屏幕上的其他玩家)本来也不该拿到你的完整效果规格,他们靠标签、表现和复制下来的蒙太奇就够了。

Minimal does not work on an ability system component that has an owning connection. The engine's own note says to use Mixed there. The reason is concrete. Cooldown time remaining and the buff list are read from the local active-effect container. Minimal never replicates that container to the owner, so the owner's cooldown UI has nothing to read. Simulated proxies — other players on your screen — should not receive your full effect specs anyway. Tags, cues, and the replicated montage are enough for them.

标签是条件语言

Tags are the condition language

FGameplayTag 是分成层级的名字,形如 Ability.Attack.Light 或 Status.Stunned。查询父标签时,子标签算数。它们在工程设置或 DefaultGameplayTags.ini 里登记,也可以用原生标签宏在 C++ 里声明。没登记就拿字符串去取,开了无效标签报错的话会直接失败。不要在角色上再存一套平行的 FName。

An FGameplayTag is a hierarchical name, Ability.Attack.Light or Status.Stunned. A query for the parent matches the child. Register tags in project settings or DefaultGameplayTags.ini, or declare native tags from C++. Requesting an unregistered tag fails when invalid-tag errors are on. Do not keep a parallel bag of FNames on the character.

眩晕不是角色上的布尔。一个持续时间效果在生效期间授予 Status.Stunned,结束时标签自动拿掉。每条不该在眩晕中释放的技能,把这个标签写进 Activation Blocked Tags。第二套系统不用记得去清布尔,因为它根本没有那份布尔。技能之间的互相取消、装备要求、免疫,走的是同一套标签,而不是角色类上越来越长的 if。

Stun is not a bool on the character. A duration effect grants Status.Stunned while it is active and drops the tag when it ends. Every ability that must not fire during stun lists that tag in Activation Blocked Tags. A second system cannot forget to clear the bool, because there is no bool. Cancel rules, equipment requirements, and immunity use the same tags, instead of a longer chain of conditionals on the character class.

属性和属性集

Attributes and attribute sets

一条属性是 FGameplayAttributeData,里面有 BaseValue 和 CurrentValue。瞬间效果改的是基础值。有持续时间的效果和永久效果(Infinite,一直在,直到被人拿掉)通过聚合器改当前值,效果移除后当前值回到只剩基础值的结果。ATTRIBUTE_ACCESSORS 宏会生成 GetHealth、InitHealth 和 GetHealthAttribute 这类访问器。属性集是 UAttributeSet 的子类,在主人的 C++ 构造函数里作为默认子对象创建,这样才会注册进组件。这件事做不了纯蓝图。

One attribute is an FGameplayAttributeData with a BaseValue and a CurrentValue. Instant effects write the base. Duration effects and infinite effects — effects that stay until something removes them — contribute modifiers through the aggregator and change the current value. When they go away, the current value falls back to whatever the base evaluates to. The ATTRIBUTE_ACCESSORS macro generates the getters, InitHealth, and GetHealthAttribute. An attribute set subclasses UAttributeSet and is created as a default subobject in the owner's C++ constructor, which is what registers it with the component. That part is not Blueprint-only.

伤害不要写成 Health = Health - Damage。那会绕过效果管线、捕获和预测。对目标应用一份效果。出生时的初始值,示例项目用一份瞬间效果灌进去,让初始化和战斗走同一条管子。InitHealth 适合在效果系统还没接上之前播种,不适合当作每次受伤的入口。

Do not apply damage as Health = Health - Damage. That skips the effect pipeline, attribute capture, and prediction. Apply an effect to the target. The samples seed starting values with an instant effect too, so spawn and combat share one pipe. InitHealth is for seeding before effects exist. It is not the doorway for every hit.

元属性(Meta Attribute)是一根管道,不是给界面看的数。常见写法是执行计算把这次伤害加进 IncomingDamage,PostGameplayEffectExecute 里读出它、扣到 Health 上,再把 IncomingDamage 写回 0。它不该复制到血条上。PostGameplayEffectExecute 只会在「效果被执行、去改基础值」时进来,也就是瞬间效果和周期结算。一个只靠持续时间修饰符加攻击力的 Buff,不会走这个回调。

A meta attribute is a pipe, not a number for the HUD. The usual pattern: an execution adds this hit to IncomingDamage, PostGameplayEffectExecute reads it, subtracts it from Health, and writes IncomingDamage back to 0. Do not replicate it onto a health bar. PostGameplayEffectExecute runs when an effect executes and modifies a base value, which means instant effects and periodic ticks. A buff that only adds attack through a duration modifier never enters that callback.

钳制要写在正确的回调上。PreAttributeBaseChange 钳基础值,PreAttributeChange 钳即将写入的当前值。只钳一边,最大生命变小时,当前生命可能暂时高于上限,直到下一次聚合。最大生命变化时按比例改当前生命,社区示例是再应用一份效果,而不是在回调里直接写属性。属性的复制写在属性集上:GetLifetimeReplicatedProps 里用 DOREPLIFETIME_CONDITION_NOTIFY,OnRep 里调用 GAMEPLAYATTRIBUTE_REPNOTIFY。

Clamp in the callback that matches the value you mean. PreAttributeBaseChange clamps the base. PreAttributeChange clamps the current value about to be stored. Clamp only one of them and a shrinking max health can leave current health above the cap until the next aggregation. When max health changes, the community sample adjusts current health in proportion by applying another effect, not by writing the attribute inside the callback. Attribute replication lives on the attribute set: DOREPLIFETIME_CONDITION_NOTIFY inside GetLifetimeReplicatedProps, and GAMEPLAYATTRIBUTE_REPNOTIFY inside the OnRep.

游戏效果

Gameplay effects

UGameplayEffect 的蓝图子类是设计师日常改的资产。持续时间政策就三种:Instant,用完即弃,改基础值;Has Duration,到期移除,存续期间改当前值;Infinite,一直留到被移除。周期(Period)用来做持续伤害,可以选择应用时是否先结算一次。

Designers live in Blueprint children of UGameplayEffect. Duration policy has three values. Instant applies and is gone, and it writes base values. Has Duration sticks until the timer ends and modifies the current value while it is up. Infinite stays until something removes it. A period turns the effect into damage over time, with an option to tick once on application.

5.3 起,一份效果在内部拆成多块 Gameplay Effect Component:标签、免疫、授予技能各自一块。编辑器里你改的仍是持续时间、修饰符和标签。拿 5.3 以前的截图去找旧的 Granted Tags 折叠栏,在新编辑器里可能会落到组件列表里。行为没有改:瞬间效果还是不会把状态标签留下来。

Starting in 5.3, an effect is split internally into Gameplay Effect Components. Tags, immunity, and granted abilities each sit on their own component. In the editor you still set duration, modifiers, and tags. A pre-5.3 screenshot that points at the old Granted Tags foldout may land you in that component list instead. The behavior did not change. An instant effect still does not leave a state tag behind.

修饰符的运算是加、乘、除、覆盖。幅度可以来自可缩放浮点(按技能等级查曲线表)、来自另一条属性、来自自定义幅度类,或来自 Set by Caller——应用前按标签把数字塞进规格,而不是烤死在资产里。源码里乘法那一档的枚举拼成了 Multiplicitive,少一个 a。在代码里搜 Multiply 会扑空。

Modifier ops are add, multiply, divide, and override. The magnitude can be a scalable float (a curve table keyed by ability level), another attribute, a custom magnitude class, or Set by Caller, which stuffs a number into the spec by tag just before apply instead of baking it into the asset. In source, the multiply op is spelled Multiplicitive, missing an a. Searching the code for Multiply misses it.

堆叠要先决定按来源算还是按目标算,新的一层会不会刷新持续时间、会不会重置周期,叠满之后是拒绝还是溢出成另一个效果。这些都是效果上的政策,不是技能里临时写的布尔。

Stacking starts with a key: by source, or by target. Then decide whether a new stack refreshes duration, whether it resets the period, and whether overflow is denied or spills into another effect. Those are policies on the effect, not bools invented inside the ability.

瞬间效果不会「在生效期间」授予标签,因为它从不进入活跃效果列表。眩晕、沉默这种状态必须用有持续时间或无限期的效果来授予标签。应用条件、免疫、移除条件也都写在效果的标签上:目标缺了必须有的标签,或身上有免疫标签,这次应用就失败。效果还可以在自己活着的时候授予一条技能,效果被拿掉,技能一并收回。武器给的技能更常见的做法是技能包,见后面 Lyra 那一节。消耗和冷却也只是技能在 Commit 时应用的两份效果。冷却效果通常什么数都不改,只授予 Cooldown.Ability.X,让同一条技能的冷却检查失败。

An instant effect cannot grant a tag "while active," because it never joins the active effect list. Stun and silence have to be duration or infinite effects. Application requirements, immunity, and removal rules are tags on the effect too. If the target lacks a required tag, or already carries an immunity tag, application fails. An effect may also grant an ability for as long as it lives. Remove the effect and the ability leaves with it. Weapons more often grant through an ability set, covered with Lyra below. Cost and cooldown are just two effects the ability applies when it commits. A cooldown effect usually changes no number. It grants Cooldown.Ability.X so the same ability's cooldown check fails.

技能

Abilities

激活顺序是:CanActivateAbility 查标签、消耗和冷却,通过后进入 ActivateAbility。CommitAbility 才真正扣费并上冷却。挥空也扣费,还是命中才扣,是设计选择,但服务器和预测客户端必须走同一条。提交失败或任何提前退出,都要 EndAbility。不结束的技能会留在活跃列表里,若它阻塞自己,就再也放不出来。

Activation order is fixed. CanActivateAbility checks tags, cost, and cooldown, then ActivateAbility runs. CommitAbility is what actually spends the cost and starts the cooldown. Whether a whiff pays is a design choice. The server and the predicting client have to make the same choice. If the commit fails, or the ability leaves early for any other reason, call EndAbility. An ability that never ends stays in the active list. If it blocks itself, it will not fire again.

实例策略:Instanced Per Actor 最常用,同一条规格在这个 Actor 上留一份实例,可以有成员状态,也可以用技能任务。Instanced Per Execution 每次激活一份新实例,结束就扔。Non Instanced 用的是类默认对象,没有每实例状态,也不能用技能任务,只适合真正瞬间、没有等待的技能。

Instancing: Instanced Per Actor is the usual choice. One instance of that spec lives on the actor, it can hold state, and it can run ability tasks. Instanced Per Execution makes a new instance per activation and throws it away at the end. Non Instanced runs on the class default object. It has no per-instance state and it cannot run ability tasks. Save it for an ability that is truly instant and never waits.

网络执行策略:Local Predicted,本机先跑,服务器确认,不同意就回滚,给玩家自己按的键。Server Only,只在服务器跑,给 AI 和不该由客户端起头的事。Server Initiated,服务器先开始,再让客户端跟上。Local Only 不上服务器。用它去改一条会复制的属性,等于承认两边可以各算各的。

Net execution: Local Predicted runs on the owning client first, the server confirms, and a rejection rolls the client back. Use it for buttons the local player presses. Server Only runs on the server. Use it for AI and for anything the client must not start. Server Initiated starts on the server, then the client follows. Local Only never touches the server. Using it to change a replicated attribute is a decision that the two machines may disagree on purpose.

输入有两代接法。老的 GAS 在技能规格上放一个整数 Input ID,把 Pawn 的输入绑到组件上,按下时调用 AbilityLocalInputPressed。Lyra 不这么做。增强输入的一次动作映射成一个标签,标签先被记成「按下」或「按住」,玩家控制器处理完本帧输入之后,再让组件激活带这个标签的规格。回调里不直接放技能。只抄了 Lyra 的绑定、没抄处理输入那一帧,就会出现「键按了,什么都没发生」。

Input has two generations. Classic GAS stores an integer input id on the ability spec, binds the pawn's input component to the ability system component, and calls AbilityLocalInputPressed on the key. Lyra does not. An Enhanced Input action maps to a tag. The tag is recorded as pressed or held. After the player controller finishes input for the frame, the component activates specs that carry that tag. The input callback does not fire the ability. Copy Lyra's binding and skip that later pass, and the key does nothing.

技能任务

Ability tasks

蓝图里那些 Wait 节点,本体是 UAbilityTask:播蒙太奇并等待、等一段时间、等目标数据、等游戏事件、等松手。技能在任务挂着的时候保持激活。蒙太奇被打断时,如果只绑了完成、没绑打断和取消,回调不来,技能就泄漏在活跃列表里。每一条引脚都要绑,并且在每条退出路径上结束技能。

The Wait nodes in Blueprint are UAbilityTask objects: play a montage and wait, wait a delay, wait for target data, wait for a gameplay event, wait for input release. The ability stays active while the task is open. If a montage is interrupted and you bound Completed but not Interrupted and Cancelled, the callback never comes and the ability leaks in the active list. Bind every pin, and end the ability on every exit.

自定义等待继承 UAbilityTask,用引擎那套创建任务的宏,结束时广播委托。不要在技能旁边再发明一套异步。被动的「着火就掉血」如果只是数字,一份周期效果就够了,不必为了掉血再开一条技能。

A custom wait subclasses UAbilityTask, uses the engine's task-creation macros, and broadcasts when it finishes. Do not invent a second async system beside this. If "on fire, lose health" is only a number, a periodic effect is the whole feature. It does not need an ability whose only job is to tick.

表现通知

Gameplay cues

表现通知的标签习惯写成 GameplayCue.Combat.Hit。一次性火花用 Static 通知。需要跟着效果活一段时间的循环光环,用 Actor 通知,这样才有 Active、While Active 和 Remove。Execute 是一次性爆发。Add / WhileActive / Remove 跟着一份非瞬间效果的寿命走。

Cue tags are conventionally named GameplayCue.Combat.Hit. A one-shot spark is a static notify. A looping aura that should live as long as the effect does is an actor notify, which is what gives you Active, While Active, and Remove. Execute is a burst. Add, While Active, and Remove follow the lifetime of a non-instant effect.

预测技能要在本机先播表现,手感才跟得上;其他人看到的是服务器广播的那一份。预测被拒绝,本机这份表现要能撤掉。Execute 经常走不可靠组播。丢一个包,少一朵火花,不能少一次伤害——伤害走的是效果,不是通知。

A predicted ability should play its cue locally or the hit feels late. Everyone else sees the cue the server broadcasts. If the prediction is rejected, the local cue has to come down with it. Execute cues are often unreliable multicasts. A dropped packet may drop a spark. It must not drop the damage. Damage moved through the effect, not through the cue.

预测:服务器仍是权威

Prediction, with the server still in charge

预测是让本机先动的头马,不是第二套权威。带预测键应用的效果,服务器用同一把键对上之后,会合并而不是叠成两份。服务器拒绝这条技能,本机已经改过的属性和已经播过的表现要收回。客户端自己掷的暴击,服务器再掷一次,两边不会自然相同。要么服务器把结果告诉客户端,要么两边用同一套确定的输入去算。

Prediction is a head start for the owning client, not a second authority. An effect applied with a prediction key is matched when the server's effect arrives with the same key, so it is reconciled instead of applied twice. If the server rejects the ability, predicted attribute changes and cues on that client come back off. A crit rolled on the client and rolled again on the server will not match by luck. Either the server tells the client the roll, or both sides compute from the same deterministic inputs.

你屏幕上的其他角色不会预测你的按键。他们看到的是复制过去的标签、表现,以及组件上那份 FGameplayAbilityRepAnimMontage。蒙太奇若只在本机任务里播放、不走这份额外复制,其他客户端看到的是一个站着的人。

Other characters on your screen do not predict your button. They see replicated tags, cues, and the FGameplayAbilityRepAnimMontage the component replicates. Play the montage only inside a local task, and skip that replicated snapshot, and every other client watches a pawn that is standing still.

瞄准和目标数据

Targeting and target data

技能要告诉服务器「这些 Actor」或「这一点」,用的是 FGameplayAbilityTargetData,通常由 Wait Target Data 这个任务送出。客户端可以先送预测的目标数据,服务器可以接受,也可以按自己的规则重算。只在客户端做一次命中检测、不把结果送去确认、服务器也不重打,联机里就会出现你打中了、服务器认为没有的分裂。

When an ability has to tell the server "these actors" or "this point," the payload is FGameplayAbilityTargetData, usually sent by the Wait Target Data task. The client may send a predicted payload. The server may accept it or trace again under its own rules. A trace that exists only on the client, with nothing sent up and no server re-trace, splits the game: you hit, the server did not.

可复用的目标 Actor、准星,以及「这一下是爆头」怎么告诉表现通知,GASShooter 做了完整示范。额外信息的做法是子类化 FGameplayEffectContext,自己写网络序列化和复制,而不是在效果资产上塞一个蓝图变量指望它跟着走。那个示例工程停在 4.27,当设计笔记读,不要当成能直接升级到 5.5 的工程。

Reusable target actors, reticles, and how a headshot reaches the cue are what GASShooter is for. Extra facts ride along by subclassing FGameplayEffectContext and writing the net serialize and duplicate yourself. A Blueprint variable on the effect asset will not magically replicate with the context. That sample stops at 4.27. Read it as a design notebook. Do not treat it as a project you can upgrade to 5.5 and keep playing.

技能包,以及 Lyra 多包了什么

Ability sets, and what Lyra adds on top

技能包是一份数据资产:要授予的技能、要应用的效果、要加上的属性集,以及收回时要用的句柄。在服务器上授予——Pawn 被控制、武器装备上、或一个游戏功能插件加载进来。句柄存下来。卸下时用这些句柄收回。不收回的话,上一把武器的开火会留在 PlayerState 上,跟着玩家穿过死亡。

An ability set is a data asset: abilities to grant, effects to apply, attribute sets to add, and the handles you need to take them back. Grant it on the server when a pawn is possessed, a weapon is equipped, or a game-feature plugin loads. Keep the handles. Remove with those handles. Leave them and the previous weapon's fire ability stays on the player state, and it follows the player through death.

Lyra 在 GAS 外面又包了三层:用 Game Feature 插件把技能包注进关卡,用 InitState 规定组件按什么顺序起来,再用前面说的标签输入。这三层不是 GAS。空白工程里还不能稳定地授予一条技能、打出一份效果之前,去读 Lyra,会把样例的模块图误认为技能系统本身。增强输入那条路径,可以先看体积小得多的 Enhanced-Input-Ability-Activation,它就是为了把 Lyra 的输入从样例里拆出来。

Lyra wraps three things around GAS. Game Feature plugins inject ability sets, an InitState machine orders component startup, and input is the tag path described above. None of the three is GAS. Reading Lyra before you can grant one ability and apply one effect in a blank project makes the sample's module graph look like the ability system. For the input path alone, Enhanced-Input-Ability-Activation is the small extract of Lyra's scheme.

建议的阅读和动手顺序

An order that finishes

第一步,空白工程。打开插件,做一条 Health,一份对自己造成伤害的瞬间效果,一条应用它的技能。GASam(引擎 5.6.1 的最小工程)和 Epic 社区教程 Your First 60 Minutes 就是这个尺寸。官方的 Best Practices for Setup 适合在这之后用来核对属性集和初始化,不要拿它当第一份阅读材料。

First, a blank project. Turn the plugin on, add Health, add an instant effect that damages yourself, add an ability that applies it. GASam, a minimal project on 5.6.1, and Epic's community tutorial Your First 60 Minutes are this size. Epic's Best Practices for Setup is the checklist to use after that, for attribute sets and init. It is a poor first read.

第二步,做一份会授予 Status.Stunned 的持续时间效果,并让技能在这个标签下被挡住。确认瞬间效果做不到这件事。第三步,把组件挪到 PlayerState,死一次再复活,看冷却还在不在。服务器和客户端的 Init 都补上,并把 PlayerState 的更新频率调高。

Second, add a duration effect that grants Status.Stunned and block the ability with that tag. Confirm that an instant effect cannot do this job. Third, move the component to the player state, die, respawn, and see whether the cooldown survived. Init on both server and client, and raise the player state's net update frequency.

第四步,按章节读 tranek 的 GASDocumentation。正文对齐的是 5.3。抄代码到更新的引擎上时,对着本机插件源码看一眼初始化、预测和目标数据有没有变。第五步,做一条 Local Predicted 的技能,里面用蒙太奇任务。开两个客户端,想办法让服务器拒绝一次,看回滚是否把血和火花一起收回。

Fourth, read tranek's GASDocumentation in chapter order. The text is current with 5.3. When you copy a snippet onto a newer engine, check init, prediction, and target data against the plugin in your tree. Fifth, build one Local Predicted ability that waits on a montage task. Run two clients, force the server to reject it, and see whether health and the spark both come back.

第六步才是 Lyra 的输入和技能包。第七步,需要武器、弹药、目标 Actor 时再打开 GASShooter。它停在 4.27。中文译文(GASDocumentation 的中文仓库)用来加快阅读,分支和数字仍以英文 README 和引擎源码为准,译文会滞后。

Sixth, Lyra's input and ability sets. Seventh, open GASShooter when you need weapons, ammo, and target actors. It stops at 4.27. Chinese translations of the manual are for reading faster. Branches and numbers still follow the English README and the engine source. Translations lag.

反复出现的坑

The mistakes that keep coming back

组件只加在蓝图里,或 InitAbilityActorInfo 只在服务器调用。复活之后化身仍指向尸体,新身体不播蒙太奇、不受效果。

The component exists only as a Blueprint add, or InitAbilityActorInfo runs only on the server. After respawn the avatar still points at the corpse, so the new body plays no montage and takes no effects.

用赋值改生命,而不是应用效果。预测、捕获和元属性管道全部落空。界面直接绑元属性,血条会在结算瞬间跳一下无关的数。

Health is assigned in place, instead of applying an effect. Prediction, capture, and the meta-attribute pipe never see the hit. Binding the HUD to the meta attribute makes the bar twitch at a number that was only a pipe.

用瞬间效果授予眩晕标签,标签不会留下。玩家组件用了 Minimal,冷却条没有活跃效果可读。PlayerState 的更新频率保持默认,标签变化像延迟半秒。

A stun tag is granted from an instant effect, so it never sticks. A player-owned component is set to Minimal, so the cooldown UI has no active effect to read. The player state's update frequency stays at the default, and tag changes look about half a second late.

技能有一条路径没调用 EndAbility。提交在客户端和服务器上不一致,资源被回滚,手感像掉血又弹回。蒙太奇只在本地任务播放,其他客户端看不到动作。表现通知里改了游戏状态。

One exit path never calls EndAbility. Commit does not match between client and server, so the resource snaps back and the hit feels like it landed and then lied. The montage plays only in a local task, so other clients see no action. A cue writes gameplay state.

从 Lyra 或 GASShooter 整项目开工。前者让你在游戏功能插件里找一个本该在空白工程里就能学会的组件;后者让你在升级 4.27 工程,而不是在学 GAS。

Starting from the whole of Lyra, or from GASShooter. Lyra sends you through game-feature plugins to find a component you could have learned in a blank project. GASShooter sends you into a 4.27 upgrade, which is a different problem from learning GAS.

名词对照

Names, left in English

中文说法引擎里的名字English
技能系统组件UAbilitySystemComponentThe hub on an actor. Abilities, effects, tags, and attribute access go through it.
属性集UAttributeSetThe C++ object that owns the numbers and their replication.
属性FGameplayAttributeDataOne stat, with a base value and a current value that modifiers evaluate into.
游戏效果UGameplayEffectA data asset that changes attributes, grants tags, or grants abilities.
技能UGameplayAbilityThe procedure for one action: may it run, what it spends, when it ends.
技能任务UAbilityTaskA latent step inside an ability, such as a montage or a target pick.
标签FGameplayTagA hierarchical name. State, requirements, and cue ids are tags, not loose strings.
表现通知GameplayCueWhat the player sees and hears. It does not decide the rules.
持有者 / 化身OwnerActor / AvatarActorWho owns the component, and which pawn is currently in the world wearing it.
预测键FPredictionKeyThe id that lets the server match a client's head start to the authoritative result.

资料

Sources worth opening

下面是整理这页时核对过、而且现在还能打开的入口。版本写在每条自己的说明里。tranek 的手册对齐 5.3,GASShooter 对齐 4.27,GASam 对齐 5.6.1。这不是网上每一篇帖子的目录。

These are the pages that were checked while writing this guide and that still opened. Each note names its engine version. The tranek manual matches 5.3, GASShooter matches 4.27, GASam matches 5.6.1. This is not a catalog of every post on the web.

官方

  • Gameplay Ability System(Unreal Engine 4.27 文档)

    仍在线的概念文档。接口细节以你所用的 5.x 插件源码和 API 页为准,不要把 4.27 的页面当现行规范。

    The conceptual docs that are still online. Treat 5.x plugin source and the API pages as current. Do not use this 4.27 page as the spec for a new project.

  • UAbilitySystemComponent API

    引擎 API 参考的一个入口(GetActivatableAbilities)。同目录下是组件的其他函数。文档站偶尔要登录 Epic 账号才能看。

    One door into the API reference, on GetActivatableAbilities. The rest of the component's functions sit in the same section. The docs site sometimes asks for an Epic login.

  • UAbilitySystemGlobals API

    全局初始化和从 Actor 查找组件的入口。对照 InitGlobalData 在 5.3 前后的差别时看这里,再看你本地的源码。

    Global init, and the lookup from an actor to its component. Use it when you are checking how InitGlobalData changed around 5.3, then confirm against your local source.

  • Your First 60 Minutes with Gameplay Ability System

    Epic 社区的一小时入门,尺度适合空白工程的第一天。

    Epic's community hour-long start. The right size for day one in a blank project.

  • Gameplay Ability System — Best Practices for Setup

    Epic 社区的接入核对表,偏属性和初始化。先做通一条技能再回来对照。

    Epic's community setup checklist, focused on attributes and init. Build one working ability before you use it as a checklist.

  • Getting Started with GAS in Unreal Engine 5.6

    社区教程,标题写明对齐 5.6。和 5.3 的旧文冲突时,以这篇和你本机 5.6 源码一起看。

    A community tutorial whose title names 5.6. Where it disagrees with a 5.3 write-up, read it next to the 5.6 plugin on your machine.

  • Learning Path: Lyra Starter Game

    Epic 在发布帖里给出的 Lyra 学习路径。先有一条自己的技能,再沿着这条路径看样例。

    The Lyra learning path Epic linked from the release post. Build one ability of your own before you follow it through the sample.

示例

  • Lyra Starter Game

    Epic 官方示例,从商城或启动器下载工程。GAS 被包在游戏功能、初始化状态机和增强输入里面。它是生产接法的样品,不是第一份教程。

    Epic's sample. Download the project from the marketplace or the launcher. GAS sits under game features, an init-state machine, and Enhanced Input. It is a production wiring sample, not the first tutorial.

  • GASam

    UE 5.6.1 的最小工程:血量、初始化效果、火球。作者声明非官方。想看清一条技能时,比 Lyra 合适。

    A minimal 5.6.1 project: health, an init effect, a fireball. Unofficial. When you want to see one ability clearly, it is a better room than Lyra.

  • Enhanced Input Ability Activation

    把 Lyra 用标签激活技能的输入路径拆成小工程。作者声明非官方。用来理解「按下只记账、帧末才激活」。

    Lyra's tag-based ability input, pulled into a small project. Unofficial. Read it for the split between recording the key and activating at the end of the frame.

  • GASShooter

    tranek 的进阶射击示例,停在 UE 4.27。武器授予技能、弹药、目标 Actor、爆头上下文都在这里。论坛发布帖可以当目录。

    tranek's advanced shooter, frozen at UE 4.27. Weapon-granted abilities, ammo, target actors, and a headshot context live here. The forum thread is a table of contents.

  • GASShooter 论坛发布帖

    作者列出这个 4.27 示例实际演示了哪些技术。先看清单,再决定要不要把工程拉下来。

    The author's list of what the 4.27 sample actually demonstrates. Read the list before you clone the project.

社区文档

  • tranek/GASDocumentation

    社区事实标准,MIT,作者声明非官方、不保证无误。正文对齐 UE 5.3,旧引擎看对应分支。最好的文档仍是插件源码,这份是地图。

    The community standard. MIT. The author says it is unofficial and not guaranteed. The text matches UE 5.3; older engines have branches. The plugin source is still the better document. This is the map.

  • GASDocumentation on DeepWiki

    别人根据该仓库生成的目录,方便跳转。数字和分支以 GitHub 上的 README 为准,不要把生成页当第二份规范。

    A generated outline of that repo, useful for jumping around. Numbers and branches follow the README on GitHub. Do not treat the generated pages as a second spec.

  • Looking into Lyra — Inputs and GAS

    沿着一次按键,把 Lyra 里的标签追到技能规格。适合已经会 GAS、想看 Epic 怎么绑输入的人。

    Follows one keypress through Lyra's tags into an ability spec. For someone who already knows GAS and wants Epic's input binding.

  • Lyra input system explained

    从配置看 Lyra 的增强输入:原生动作和技能动作分开,技能动作只负责把标签交给组件。

    Lyra's Enhanced Input from the config side. Native actions and ability actions are split. Ability actions only hand a tag to the component.

  • The six pieces of GAS

    短文,把组件放在角色还是 PlayerState 说清楚,并强调属性只能经效果修改、状态用标签。

    A short piece on character versus player state, and on the two rules that prevent most bugs: change attributes through effects, and keep state in tags.

  • Lyra abilities without living in C++

    在 Lyra 工程里用蓝图和数据资产加技能、效果和消耗。前提是你已经接受 Lyra 那套 C++ 骨架。

    Adding abilities, effects, and costs inside a Lyra project from Blueprints and data assets. It assumes you are keeping Lyra's C++ skeleton.

  • GAS Companion(Fab / 商城)

    付费插件,用来补 GAS 对蓝图不友好的部分,例如用向导生成属性集的 C++。它不是引擎的一部分,也代替不了上面的概念。

    A paid plugin that papers over the parts of GAS that are hostile to Blueprint, including a wizard that generates attribute-set C++. It is not part of the engine, and it does not replace the concepts above.

中文

  • GASDocumentation 中文译文(q894829927)

    社区译文,用来加快阅读 tranek 手册。和上游不一致时以上游英文和引擎源码为准。

    A community translation for reading tranek's manual faster. Where it drifts from upstream, the English README and the engine source win.

  • GASDocumentation 5.3 中文(DriedMachine)

    标明对齐 5.3 的另一份译文。同样不是官方文档,不要单独当作现行规范。

    Another translation, labeled as 5.3. Also unofficial. Do not use it alone as the current spec.

  • GAS 网络同步分析

    社区长文,按预测、效果增量复制、标签、表现通知和蒙太奇拆网络路径。文中的分支以你本地 AbilitySystemComponent 源码复核后再采用。

    A long community article that splits prediction, effect delta replication, tags, cues, and montages into separate net paths. Check any branch it describes against AbilitySystemComponent in your tree before you adopt it.

  • Lyra 技能与模块拆解笔记

    按 Lyra 的系统列了阅读顺序:技能包、初始化状态机、输入、装备。是目录,不是第二套 GAS 实现。

    A reading order over Lyra's systems: ability sets, the init-state machine, input, equipment. It is an index, not a second implementation of GAS.