UE5 GAS Base

GAS Base

前言

  • 4.27好多bug啊, 例如GA的Trigger Source的问题
  • 使用版本: 5.2.1, 注意版本问题GAS版本之间是有差异的, 4.27和5.2.1差异就很大
  • 本文旨在描述GE/GA/GC的细节面板, 使用时可参考,不是入门教程
  • 大多都亲自试验过, 能保证正确性(参考链接里内容可能有错误,我进行二次勘误了)
  • 真的很想吐槽有些文章,照着注释(GAS的注释也一塌糊涂)想当然解释,不亲自实验一下,误人子弟

Gameplay Ability

1. Tag

  1. Ability Tags:该GA的标签。
  2. Cancel Abilities with Tag:激活该GA时,打断其他拥有所选标签的GA。
  3. Block Abilities with Tag:激活该GA时,阻止激活拥有所选标签的GA(已经激活的不会被中断)。
  4. Activation Owned Tags:激活该GA时,赋予ASC所选GA。
  5. Activation Required Tags:激活GA时,ASC需要的标签。
  6. Activation Blocked Tags:激活GA时,ASC不能有的标签。
  7. Source Required Tags:激活GA时,Source需要的标签。

    系统如何看待"Source Tags"并不是很明显,因为没有任何地方对它做出解释,不过你可以使用GameplayEvents特性,携带Payload来激活技能。GameplayEvent能够传递一个结构体,里面有一个InstigatorTags,可以用作Source Required和Source Blocked Tag的检测。当Payload包含所有指定的Tag,技能允许被激活。

  8. Source Blocked Tags:激活GA时,Source不能有的标签。
  9. Target Required Tags:激活GA时,Target 需要的标签。

    同样的规则,只不过这里使用Payload结构体中的TargetTags。InstigatorTags应该使用技能所有者和触发者(通常是Character类)的描述性Tag来填充,然后TargetTags应该使用技能攻击目标的相关信息来填充。代码并没有强制你如何填充GameplayEvent数据中的Tag容器,你可以想咋整就咋整,这是真的。

  10. Target Blocked Tags:激活GA时,Target 不能有的标签。

2. Input

  • Replicate Input Directly: 设为true, Client会一直向Server同步输入的按下(Press)和松开(Release)事件。Epic不建议使用该选项, 推荐使用AbiliyTask的Wait Input ReleaseWait Input Press

触发事件:

/** Direct Input state replication. These will be called if bReplicateInputDirectly is true on the ability and is generally not a good thing to use. (Instead, prefer to use Generic Replicated Events). */
UFUNCTION(Server, reliable, WithValidation)
void UAbilitySystemComponent::ServerSetInputPressed(FGameplayAbilitySpecHandle AbilityHandle);

UFUNCTION(Server, reliable, WithValidation)
void UAbilitySystemComponent::ServerSetInputReleased(FGameplayAbilitySpecHandle AbilityHandle);

3. Advanced

  • Replication Policy: 不要使用该选项. 这个名字会误导你并且你并不需要它. GameplayAbilitySpec默认会从服务端向所属(Owning)客户端同步, 上文提到过, GameplayAbility不会运行在 Simulated Proxy 上, 其使用 AbilityTaskGameplayCue 来同步或者RPC视觉变化到 Simulated Proxy. Epic的Dave Ratti已经表明要在未来移除该选项的意愿.
  • Instancing Policy: GameplayAbility的实例化策略决定了当GameplayAbility激活时是否和如何实例化.
    • Non-Instanced: GameplayAbility操作其ClassDefaultObject, 没有实例创建.
      • 性能最好,但是不能存储状态,不能有动态变量AbilityTask
    • Instanced Per Execution: 每有一个GameplayAbility激活, 就有一个新的GameplayAbility实例创建,同一种类型的GA会被重复执行
      • 性能较差,默认情况。
    • Instanced Per Actor: 每个ASC只能有一个在激活之间复用的GameplayAbility实例(首个Activate的GA未End时,重复的GA会被忽略)
      • 最常使用的策略,实例GA不会轻易被销毁
  • Server Respects Remote Ability Cancellation: 如果Client的GameplayAbility由于玩家取消或者自然完成时, 就会强制它的Server版本结束而不管其是否完成。反之一样
  • Retrigger Instanced Ability: 仅当Instancing PolicyInstanced Per Actor起作用, 若为true,首个Activate的GA未End时,重复的GA会End(不是Cancel)正在执行的GA然后重新Activate
  • Net Execution Policy: GameplayAbility的网络执行策略(Net Execution Policy)决定了谁该以什么顺序运行该GameplayAbility
    • Local Only: GA只运行在所属(Owning)客户端. 这对那些只需做本地视觉变化的Ability很有用. 单人游戏应该使用Server Only
    • Local Predicted: GA首先在所属(Owning)客户端激活, 之后在服务端激活. 服务端版本会纠正客户端预测的所有不正确的地方
    • Server Only: GA只运行在服务端. 被动GameplayAbility一般是Server Only. 单人游戏应该使用该项.
    • Server Initiated: GA首先在服务端激活, 之后在所属(Owning)客户端激活.
  • Net Security Policy: GameplayAbility的网络安全策略决定了Ability应该在网络的何处执行. 它为尝试执行限制Ability的客户端提供了保护.
    • ClientOrServer: 没有安全需求. 客户端或服务端可以自由地触发该Ability的执行和终止.
    • ServerOnlyExecution: 客户端对该Ability请求的执行会被服务端忽略, 但客户端仍可以请求服务端取消或结束该Ability.
    • ServerOnlyTermination: 客户端对该Ability请求的取消或结束会被服务端忽略, 但客户端仍可以请求执行该Ability.
    • ServerOnly: 服务端控制该Ability的执行和终止, 客户端的任何请求都会被忽略.

4. Costs

内部判断逻辑: CurrentValue + CostValue < 0.f

注意:

  • 必须要显式调用CommitAbility之后才能提交Cost, 若不Commit但是一次性Cost导致 CurrentValue<0.f 还是会导致技能放不出来
  • 用的CurrentValue判断, 理论上GE是否设置Period都可以用

5. Triggers

Triggers Source:

  • Gameplay Event: 当Owner收到一个带有Tag的Gameplay Event(不是Gameplay Effect的GE!)时调用一次GA,此时Owner不会拥有对应的Tag。
  • Owned Tag Added: 当Owner获取对应Tag的时候调用一次GA,失去Tag不会Remove GA,后续可以通过其它方式调用
  • Owned Tag Present: 当Owner获取对应Tag的时候调用一次GA,失去TagRemove GA,GA若执行未完成会被Cancel

6. Cooldowns

注意事项:

  • GE的GrantedTags设置Tag后才能起作用。
  • 本质上通过Tag来限制, 通过其它方式为ASC添加对应的Tag后, GA也不能释放。Cooldowns GE只是确定了GA的Cooldown Tag罢了

Gameplay Effect

1. GameplayEffect

Use Curve Table: 根据GE的 Level 去查询Curve Table得到对应值,有乘数则会与其相乘。GE Level = 0 相当于 1

Magnitude Calculation Type:

  • Scalable Float: 指定浮点数
  • Attribute Based: 捕获Attribute再加以运算
    • 计算规则 Coefficient * (PreMultiplyAdditiveValue + AttributeToCapture) + PostMultiplyAdditiveValue = Magnitude
    • Backing Attribute:
      • Attribute Source: Target或者Source,GE的作用者和发出者
      • Snapshot:Snapshotting意味着当GameplayEffectSpec创建时捕获该Attribute, 而No Snapshotting意味着当GameplayEffectSpec应用时捕获该Attribute.
    • Attribute Curve: 用捕获的Attribute值去查询Curve,然后放进公式计算,而不是直接使用
    • Attribute Calculation Type:
      • Attribute Magnitude: 捕获Attribute的 CurrentValue
      • Attribute Base Value: 捕获Attribute的 BaseValue
      • Attribute Bonus Magnitude: 捕获Attribute的 CurrentValue-BaseValue
    • Source Tag Filter: 源码注释如下

      Filter to use on source tags; If specified, only modifiers applied with all of these tags will factor into the calculation

      • 实际测试并不起作用, 观察源码逻辑似乎也没有使用这个参数实际对这次Magnitude值产生什么影响(可能是预留参数?等我研究清楚再补上)
    • Target Tag Filter:

      Filter to use on target tags; If specified, only modifiers applied with all of these tags will factor into the calculation

  • Custom Calculation Class: GameplayModMagnitudeCalculation Class,自定义运算得出返回值作为Magnitude。可参考 自定义Calculation Class
    // 重载函数
    virtual float CalculateBaseMagnitude_Implementation(const FGameplayEffectSpec& Spec) const override;
    
    • 得到返回值后可以在GE中进一步修改,计算规则 Coefficient * (PreMultiplyAdditiveValue + ReturnMagnitude) + PostMultiplyAdditiveValue = Magnitude
    • Final Lookup Curve: 用上述公式计算得到的Magnitude去查询Curve作为最终的Magnitude
  • Set by Caller: 从Caller中得到Magnitude
    • ASC->MakeOutgoingSpc->AssignSetByCallerMagnitude
1.1 Duration Policy
  • Instant: 立即启用,用以改变属性的BaseValue。因为是瞬时的效应,不应该用来添加GameplayTags
  • Duration: 拥有持续时间,若无Period修改的是属性的CurrentValue, 有则每次执行相当于Instant,修改的是BaseValue。可以添加Gameplay Tags。
    • Duration = -1 , 数值不会改变, 相当于Infinite;
    • Duration <= 0 , 数值会随时间逐步减少, 但不会中断也相当于Infinite
    • 所以请注意, 首次给Duration赋值一定要>0
  • Infinite: 持续时间是永久,但可以手动移除。若无Period修改的是属性的CurrentValue, 有则每次执行相当于Instant,修改的是BaseValue。可以添加Gameplay Tags。
1.2 Modifiers
  • Attribute: 要作用的Attribute
  • Modifier Op: 修改方式
    • Add: Attribute += Magnitude
    • Multiply: Attribute *= Magnitude
    • Divide: Attribute /= Magnitude
    • Override: Attribute = Magnitude
    • Invalid: 应该没用, 选择这个引擎会触发Assert
  • Source Tags: 根据GASDocumentation

    SourceTags and TargetTags can be set for each Modifier. They work the same like the Application Tag requirements of a GameplayEffect

    • 但似乎我实际应用起来没有对单个Modifier起作用,不知道是不是我的操作方式不对,此处存疑等我弄明白再补上去
  • Target Tags:
1.3 Executions

GameplayEffectExecutionCalculation Class, 可参考 自定义Calculation Class

// 重载函数
virtual void Execute_Implementation(const FGameplayEffectCustomExecutionParameters& ExecutionParams, FGameplayEffectCustomExecutionOutput& OutExecutionOutput) const override;
1.4 Conditional Gameplay Effects

当GE成功Apply(注意是Apply,在不满足Ongoing Tag Requirements的条件下也是可以生效的),会产生附加GE

  • Effect Class: 附加GE的Class
  • Required Source Tags:需要Source的ASC含有的Tags

2. Period

Duration与Infinite设置了以后(Period != 0),每次触发相当于Instant,会修改BaseValue

  • Execute Periodic Effect on Application: t=0的时候是否触发, 默认=true
  • Periodic Inhibition Policy ----------> 与每次是否成功执行有关(Ongoing Tag Requirements)
    • Never Reset:周期的时间会继续,就好像抑制没有发生过一样。(依旧每次尝试执行)
    • Reset Period:重置周期。下一次执行将在移除抑制后的一个完整周期内发生。(会重新SetTimer
    • Execute and Reset Period: 立即执行并重置周期。(抑制接触后会立马调用一次,然后SetTimer。SetTimerForNextTick->SetTimer

GE Period的执行是通过Timer来实现的,若Ongoing Tag Requirements未满足GE会被标记为bIsInhibited = true(这个变量在每次执行的时候会被拿来判断, 为false才能执行)

Periodic Inhibition Policy的作用,拿个例子来说一下。

GE1: Duration = 10s , Period = 1s. Modifiers: Health -= 10, Ongoing Tag Requirements:GE.Test

GE2: Duration = 2.2s, GrantedTags:GE.Test

初始时ASC没有Tag:GE.Test, 但Apply GE1,显然GE1不会起作用。若在2.5s Apply GE2,ASC会得到Tag:GE.Test,然后触发回调FActiveGameplayEffectsContainer::OnOwnerTagChange, 随后标记GE1 bIsInhibited = false。4.7s ASC失去Tag:GE.Test,标记GE1 bIsInhibited = true

此时情况如下所见:

  • Never Reset:3.0s照常执行GE, 检测到 bIsInhibited = false 正常执行 Health -= 10; 4.0s类似; 5.0s执行失败
    • 执行时间: 3.0s 4.0s
    • 效果Health -= 20
  • Reset Period:2.5s 在标记bIsInhibited = false的同时, 会重新SetTimer,因为Timer的覆盖性(同一个Handle,Timer重新Set以前的会失效),原来执行的Period会重新计算,所以下一次执行时间为3.5s; 4.5s执行第二次, 5.5s执行失败;
    • 执行时间:3.5s 4.5s
    • 效果Health -= 20
  • Execute and Reset Period:Reset Period相比, 在SetTimer之前会SetTimerForNextTick。所以2.5s会多执行一次
    • 执行时间:2.5s 3.5s 4.5s
    • 效果Health -= 30

3. Application

设置GE的应用概率和条件。

  • Chance to Apply to Target:概率
  • Application Requirement:GameplayEffectCustomApplicationRequirement类—>重载CanApplyGameplayEffect函数

4. Overflow

  • Overflow Effects: Stakc溢出后, 可选择Apply的GE
  • Deny Overflow Application: 溢出的GE不会影响Stack的刷新。比如Stack Limit Count=2,当第3个GE想要作用时,因为数量的限制不会叠加,但若Stack Duration Refresh Policy != NerverSet, 会刷新Duration, Period同理
  • Clear Stack on Overflow: Stack溢出时, 是否会清空Stack。当Deny Overflow Application = true时才能勾选

5. Expiration

当Duration Policy不为Instant时, 才有此逻辑

  • Premature Expiration Effect Classes: 打断时Apply的GE。
  • Routine Expiration Effect Classes: 正常结束时Apply的GE

6. Display

  • Require Modifier Success to Trigger Cues:当GE Modifiers或者Executions成功Apply时才能触发Cue
  • Suppress Stacking Cues:多个GE存在Stack中时,是否只响应第一个GE
    • 若勾选了,当多个GE存在于Stack时,只有第一个GE才能触发GC的On ActiveWhile Active事件
  • Gameplay Cues:
    • Magnitude Attribute: 选定一个Attribute获取它这次修改值传递给GC,可通过GC Parameters的 Raw Magnitude 获得
      • 比如说这次GE修改了Health,修改值为-10,则Raw Magnitude=-10。
    • Min Level:
      • Max Level配合使用,将GE Level标准化
      • 计算规则:(GE Level - Min Level) / (Max Level - Min Level) Clamp 0.f-1.f
      • 可通过GC Parameters的 Normalized Magnitude 获得
    • Max Level:
  • UIData: GameplayEffectUIData类

GE的Duration Policy对GC触发事件类型的影响

  • Instant: 立即触发On Execute事件
  • Duration:
    • Has Period: 最开始会触发On ActiveWhile Active事件,然后每次Period执行一次On Execute事件。Duration结束会触发On Remove事件。GE被Remove或抑制也会执行On Remove事件
    • No Period: 最开始会触发On ActiveWhile Active事件,Duration结束会触发On Remove事件。GE被Remove或抑制也会执行On Remove事件
  • Infinite: 与Duration类似

注意事项:

  • 关于On Remove事件的触发对于GC_Actor来说,只有勾选Auto Destroy on Remove才能正确执行,不然只有GE第一次作用才能触发,后续不会再次触发
  • 理论上GC类型的选择对于事件的触发无影响,但是
    • GC_Static直接操作ClassDefaultObject(意味着没有实例),对于Instant效果(像击打伤害)是极好的.
    • GC_Actor会在添加(Added)时生成一个新的实例, 因为其是实例化的, 所以可以随时间推移执行操作直到被移除(Removed). 这对循环的声音和粒子效果是很好的, 其会在持续(Duration)或无限(Infinite)GameplayEffect被移除或手动调用移除时移除. 其也自带选项来管理允许同时添加(Added)多少个(多个相同效果的应用默认只创建一个实例)

7. Tags

  • GameplayEffectAssetTag: 标识GE的Tag
    • Combined Tag为计算结果,不可编辑。 计算方式是 继承的Tag + Added - Removed
  • GrantedTags: GE会赋予目标ASC的Tag,仅适用于Infinite和Has Duration的GE, GE失效后,Tag会从ASC上移除
    • Combined Tag为计算结果,不可编辑。 计算方式是 继承的Tag + Added - Removed
    • Instant不起作用
  • GrantedBlockedAbilityTags: 当GE存在时,拥有这些Tag的GA不能执行。(与GA的Block Abilities with Tag作用一致)
    • Combined Tag为计算结果,不可编辑。 计算方式是 继承的Tag + Added - Removed
    • Instant不起作用
  • Ongoing Tag Requirements: GE执行需要/不需要这些Tag, 这些标签会在 每次 执行时起作用。on/off,GE可以被Apply但off and do nothing
    • Instant会起作用
  • Application Tag Requirements: GE应用需要/不需要这些Tag, 这些标签只会在 第一次 应用Effect时才会被考虑, 而不是在每次周期执行时。pass/faild
    • Instant会起作用
  • Removal Tag Requirements: 当拥有/未拥有这些Tag,GE会被移除。GE持续时间内都有效
    • Instant会起作用
  • Remove Gameplay Effect Query: 更复杂的Remove GE的方法(笔者分析源码得出以下结论,但是实验的时候没有起作用,不能进行筛选 UE5.2.1)
    • Custom Match Delegate BP: 一个Dynamic Unicast Delegate公开到蓝图中使用(但是我没发现怎么在蓝图使用), 返回bool
    • Owning Tag Query:查询对应GE的GameplayEffectAssetTag + GrantedTags + DynamicGrantedTags
      • DynamicGrantedTags是GE Spec动态增加的GrantedTags---->ASC->MakeOutgoingSpec->AddGrantedTags
    • Effect Tag Query:查询对应GE的GameplayEffectAssetTag + DynamicAssetTags
      • DynamicAssetTags是GE Spec动态增加的AssetTag---->ASC->MakeOutgoing Spec->AddAssetTags
    • Source Tag Query:查询对应GE的Source Tags
    • Modifying Attribute:查询对应GE修改的Attribute
    • Effect Source:查询对应GE的Source Object
    • Effect Definition:查询对应GE的Class
  • Remove Gameplay Effects with Tags: 当GameplayEffect成功Apply后, 如果位于目标上的该GE在其Asset Tags或Granted Tags中有任意一个本标签的话, 其就会自目标上移除。
    • Combined Tag为计算结果,不可编辑。 计算方式是 继承的Tag + Added - Removed
    • 只在Apply时起作用, 若带有Tag的GE是在Apply之后添加的,是不能删除的
    • Instant会起作用

8. Immunity

在GE持续时间内,赋予GE作用目标免疫其它GE能力(看其它文章说可以免疫GA,笔者未测试出这个效果)

  • GrantedApplicationImmunityTags:
    • Require Tags:其它GE有这些Tags(必须全部有)就会被免疫掉,可以免疫自己保证同一时间只有一个GE生效(Statck也不能生效)
    • Ignore Tags:未测试出结果(按理说是GE没有这些Tags就会被免疫,但是不是的)
  • Granted Application Immunity Query: 更复杂的GE判断,见 Tag-Remove Gameplay Effect Query解释(笔者同样没有实验成功这个功能)

使用该系统可以在GameplayEffect被免疫阻止时提供UAbilitySystemComponent::OnImmunityBlockGameplayEffectDelegate委托(Delegate).

9. Stacking

当Duration Policy不为Instant时,才有Stack的概念

  • Stacking Type: 叠加栈在目标身上or施法者身上

    举个例子,假设层数为3,如果是by Target模式,那么3个敌人对我释放的Debuff只能叠三层。如果是by Source模式,那么3个敌人可以对我叠加9层Debuff。

    每层Effect如果是Modifiers来计算,则为直接叠加的效果,比如用Modifiers来增加3攻击力,则第一层为增加3攻击力,则第二层为增加6攻击力,则第三层为增加9攻击力,而如果需要根据层数不同而改变增加的值,则需要使用Executions。

  • Stack Limit Count: 层数
  • Stack Duration Refresh Policy: Apply新GE时是否刷新Duration, 默认情况Overflow的GE会影响Stack刷新
  • Stack Period Reset Policy: Apply新GE时是否刷新Period, 默认情况Overflow的GE会影响Stack刷新
  • Stack Expiration Policy: 当一层GE的Duration到期后的处理方式
    • Clear Entire Stack: 清空全部层数,如LOL征服者。
    • Remove Single Stack and Refresh Duration:清空一层,如LOL致命节奏。
    • Refresh Duration:不清空,相当于无限长的Duration,但可以通过调用FActiveGameplayEffectsContainer::OnStackCountChange(FActiveGameplayEffect& ActiveEffect, int32 OldStackCount, int32 NewStackCount)方法来自己处理细节,如一次掉两层。

使用细节:

  • 开启Stack的方法为设置Stacking Type不为None
  • 开启Stack后, Stack Limit Count层数为0代表可以无限叠加
  • 不开启Stack, 多个GE同时起作用, 单独计算自己的Duration互不干扰

10. Granted Abilities

当Duration Policy不为Instant时,GE触发会赋予 Target GA。

InputID: 如果使用旧版输入,每一个操作映射都对应着一个枚举值,输入对应的枚举值就可以将这个新GA绑定到输入上。操作可参考Ability和绑定输入

Removal Policy:

  • Cancel Ability Immediately: GE失效后,若Ability正在执行, 立即Cancel并Remove这个Ability
  • Remove Ability on End: GE失效后,若Ability正在执行, 允许其执行完毕,并Remove这个Ability
  • Do Nothing: GE失效后,不会Remove也不会Cancel,相当于永久拥有此Ability

Gameplay Cue

介绍GC_Actor部分参数

  • Auto Destroy on Remove: 是否在On Remove事件后进行自动Destory Recycle(不是销毁Actor)
    • 一般都是勾选上的,不然on Remove事件的触发会出现问题(见GE 6.Display)。
    • On Remove事件不会销毁Acotr,只是进行了SetActorHiddenInGame(true)
  • Auto Destroy Delay: 勾选了Auto Destroy on Remove后,经过多少秒进行Destory
  • Auto Attach to Owner: GC是否跟随Owner,若为true则会随着Owner移动。有性能损耗,需权衡
  • Is Override: 这个GC是否会覆盖其它GC. 例如有两个GC, Tag分别为GC.One.Two与GC.One。若你通过GE调用GC.One.Two,若该值为false则会调用GC.One.Two与GC.One,若该值为true,则只会调用GC.One.Two
  • Unique Instance Per Instigator: 这个GC是否为每个Instigator增加一个新的Instance? 例如,如果两个Instigator对同一个目标应用GC,我们是创建两个这样的GameplayCue Notify Actor还是一个?如果GC只是在目标上播放FX或声音,则不需要唯一Instance。如果此Notify将一个光束从Instigator附加到目标,则每个Instigator确实需要一个唯一的Instance。
  • Unique Instance Per Source Object: 与Unique Instance Per Instigator类似,只不过判断目标是Source Object
    • Source ObjectInstigator对应着Parameters上的
    • 默认情况对于同一个目标,GC只会产生一个Instance
  • Allow Multiple on Active Events: 当GC正在执行时,来一个请求再次触发GC,是否会再次触发On Active事件
  • Allow Multiple While Active Events: 当GC正在执行时,来一个请求再次触发GC,是否会再次触发While Active事件
  • Num Preallocated Instances: 为GC Instance预先分配内存空间

参考

猜你喜欢

转载自blog.csdn.net/qq_52179126/article/details/131860252