UE GAS笔记
UE GAS笔记核心概念
状态暗示: 状态由两部组成:Attribute、GameplayTag。
[*]Attribute代表数值类状态,例如移动速度、攻击力。代码定义如图所示:
BaseValue代表永久改变的部门,CurrentValue代表当前最新的值,是由基础值加上buff改变值。瞬时或周期性的GE会直接改削BaseValue,持续性GE则是在BaseValue的基础上给出影响值计算出CurrentValue。属性改削具体实现:通过Aggregator计算所有Modifier的改削,然后进行最大最小值的限制再设置给CurrentValue。一个FGameplayAttribute 对应一个 FAggregator。具体可以细看UAbilitySystemComponent.ActiveGameplayEffects.AttributeAggregatorMap相关代码。
[*]GameplayTag相较于传统用枚举值来表达状态有一个好处:Tag具备分门别类,可以使用父Tag代表一组Tag。
GameplayEffect: 可以理解成Buff,改削状态。简写GE。GE里可以通过配置Modifiers来改削Attribute,配置GrantedTags则可以在GE的所有者身上添加Tag。此外GE还可以配置:GE堆叠法则、赋予技能等。
GameplayAbility: 技能,可以添加GE、播放蒙太奇、发送事件、等待事件触发。可以通过Tag实现技能间的打断、互斥、免疫等。以及输入的绑定。 重要函数介绍:
[*]CanActivateAbility()- 判定技能是否可以激活。
[*]TryActivateAbility() - 测验考试激活技能。会先调用CanActivateAbility()进行判断。会措置网络同步以及技能预测相关逻辑。
[*]ActivateAbility() - 技能逻辑写在这里,子类需要override此函数。
[*]CommitAbility() - 应用技能消耗(技能冷却、法力消耗...)。别忘记在ActivateAbility()里调用此函数。
[*]CancelAbility() - 从外部中断技能
[*]EndAbility() - 技能结束自身,暗示技能执行完毕。
UAbilitySystemComponent 角色身上的技能大管家。主要功能涉及到:属性集的打点、当前角色拥有的技能、激活中的技能、挂载了哪些GE、GameplayTag的打点。
放上大钊总结的图:
视频地址
技能预测
Overview of Gameplay Ability Prediction GAS预测的部份:技能的激活、触发事件、GameplayEffect的应用(属性的改削、Tag的改削)、Gameplay Cue、蒙太奇。 未预测的部份:GameplayEffect的移除、GameplayEffect的周期性效果。 需要解决的问题:
[*]Undo:如何打消掉败的预测所造成的影响
[*]Redo:如何避免处事器同步过来的效果跟当地预测的效果反复应用(属性的改削、蒙太奇的播放...)
[*]Dependencies:如何打点彼此独立的预测以及链式预测
<hr/>实现细节
PredictionKey PredictionKey是客户端侧生成的独一ID。客户端会将PredictionKey发到处事器,并将预测的行为以及副感化关联到PredictionKey。处事器可能接受也可能拒绝PredictionKey,当接受Key的时候也会将处事器侧的副感化跟这个PredictionKey进行关联起来。
技能的激活 当客户端预测一个技能的激活的时候,它会明确的去询问处事器,然后处事器也会明确地回答。一旦技能被预测激活,客户端就会拥有一个预测窗口(prediction window),在此中所发生的预测副感化(side effects)将不会明确地询问处事器。例如,我们不会直接询问:我能减少魔法值吗?我能将这个技能设置成冷却中吗?。这些动作会被认为跟技能的激活在逻辑上是原子操作(logically atomic )。 AbilitySystemComponent提供了一系列的函数来辅佐客户端和处事器之间交流技能的激活:TryActivateAbility -> ServerTryActivateAbility -> ClientActivateAbility(Failed/Succeed).
[*]客户端侧调用TryActivateAbility,里面会生成新的预测键(FPredictionKey)而且调用ServerTryActivateAbility。
[*]客户端继续执行,使用前面生成的预测键调用ActivateAbility
[*]在ActivatAbility调用过程中发生的任何副感化(GE、蒙太奇)都将与前面的预测键进行关联
[*]处事器会在ServerTryActivateAbility里决定技能是否实际发生,调用ClientActivateAbility(Failed/Succeed)
[*]如果客户端收到ClientAbilityFailed会当即kill技能,并回滚掉跟之前预测键相关联的副感化(GE、蒙太奇)。
[*]回滚是通过FPredictionKeyDelegates 以及 FPredictionKey::NewRejectedDelegate/NewCaughtUpDelegate/NewRejectOrCaughtUpDelegate来实现的。
GameplayEffect的预测 GameplayEffect被认为是预测的副感化。
[*]GameplayEffect在客户端侧的应用依赖于一个有效的预测键
[*]一个GameplayEffect被预测,与之关联的Attributes、 GameplayCues、GameplayTags将被预测
[*]当FActiveGameplayEffect 被创建的时候,会存储对应的预测键
[*]瞬间的GameplayEffect会在属性预测里解释
[*]在处事器侧不异的预测键也会被设置在FActiveGameplayEffect,而且会被复制到客户端
[*]在客户端侧收到一个网络复制下来的FActiveGameplayEffect而且带有一个有效的预测键的时候,客户端会去查抄当地是否有一个ActiveGameplayEffect拥有不异的预测键,如果找到一个匹配的那么我们将不执行'on applied'之类的逻辑,例如GameplayCues。这样就解决了反复执行的问题。但客户端将会短暂的有两个不异的GameplayEffects在我们的ActiveGameplayEffects容器里。
[*]同时,UAbilitySystemComponent::ReplicatedPredictionKey将会追赶上来然后预测的副感化就会被移除掉。在移除的时候,也会再次去查抄预测键来决定是否应该执行相关的移除逻辑。
[*]客户端侧预测的GE无论处事器侧给出的答复是否决还是接受城市被移除
属性预测 attributes预测的基本思想是只预测相对改变值而不是绝对值。我们不应该去预测我们有90的法力,而是预测减少了10法力,直到处事器确认了我们的预测键。对于瞬时性改削会改削成无限时长的改削直到预测的和解。对于属性同步跟预测造成的覆盖问题,我们可以通过将处事器同步下来的值作为Base Value而不是final value,然后在每次发生属性同步后从头聚合新的Final value。
[*]我们会把Instant类型的GE当作无限持续时间的GE。相关代码在UAbilitySystemComponent::ApplyGameplayEffectSpecToSelf.
[*]必需要将attributes的网络同步设置成REPNOTIFY_Always,因客户端会进行预测性的提前改削。
[*]属性的RepNotify里记得使用GAMEPLAYATTRIBUTE_REPNOTIFY宏
预测间的依赖 在某些情况下会有:技能X激活当即触发了一个事件,这个事件激活了技能Y,而Y又激活了技能Z。这时候的预测依赖链就是X->Y->Z。这里的每一个技能都可能被处事器端否决掉。如果Y技能的激活被否决了,那么Z技能就不成能激活。但处事器从来就没运行过Z技能的激活,也就更不会发送Z被否决的通知了。为了解决这个问题,我们需要成立一个Base PredictionKey的概念。当调用TryActivateAbility的时候,我们传入当前的PredictionKey。这个PredictionKey将作为其他新PredictionKey的Base PredictionKey。通过成立PredictionKey的链式依赖,可以达到否决Y的同时否决Z。 这里有一个细节。在X->Y->Z链式情况下,处事器侧只收到了X技能的PredictionKey,当处事器测验考试激活Y和Z技能的时候只能使用原始的PredictionKey。然而在客户端侧则是每次TryActivateAbility的时候城市生成新的PredictionKey。
Prediction Windows
As stated, A prediction key is only usable during a single logical scope. Once ActivateAbility returns, we are essentially done with that key. If the ability is waiting on an external event or timer, by the time itreturns, we will have gotten a confirm/reject from the server. Any side effects produced after this will no longer be tied to the lifespan of the original key.
This isn't that bad, except that abilities will sometimes want to react to player input. For example, 'a hold down and charge' ability wants to instantly predict some stuff when the button is released. It is possible to create a new prediction window within an ability with FScopedPredictionWindow.
FScopedPredictionWindows provides a way to send the server a new prediction key and have the server pick up and use that key within the same logical scope.
蒙太奇预测 蒙太奇在预测掉败的时候会被遏制
<hr/>Unsupported / Issues/ Todo
Event没有被显示的复制。
预测Meta Attributes(伤害值、治疗值) vs 真实的attributes(血量)
预测周期性的GameplayEffects
资料保举
[*]官方GAS文档
[*]官方ARPG例子
[*]GASDocumentation
[*]GASDocumentation_Chinese
[*]虚幻引擎游戏技能系统文档
[*]深入GAS架构设计 | EpicGames 大钊
[*][中文直播]第31期|GAS插件介绍(入门篇) | 伍德 大钊
[*][英文直播]Gameplay Abilities框架介绍 | A Guided Tour of Gameplay Abilities(官方字幕)
[*]UE4的GAS探究三:弱网延迟与预测Prediction
[*]Overview of Gameplay Ability Prediction
[*]UE-GAS架构分析(三)(GameplayEffect)
[*]虚幻四Gameplay Ability System入门(6)-Gameplay Effect详解(1)Modifier
[*]虚幻插件GAS分析10 所有AbilityTask原生类盘点
[*]UE技能系统—2.GameplayEffect 你用废了吗?(一)
页:
[1]