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的周期性效果。
需要解决的问题:

  1. Undo:如何取消失败的预测所造成的影响
  2. Redo:如何避免服务器同步过来的效果跟本地预测的效果重复应用(属性的修改、蒙太奇的播放…)
  3. Dependencies:如何管理相互独立的预测以及链式预测

实现细节

PredictionKey
PredictionKey是客户端侧生成的唯一ID。客户端会将PredictionKey发到服务器,并将预测的行为以及副作用关联到PredictionKey。服务器可能接受也可能拒绝PredictionKey,当接受Key的时候也会将服务器侧的副作用跟这个PredictionKey进行关联起来。

技能的激活
当客户端预测一个技能的激活的时候,它会明确的去询问服务器,然后服务器也会明确地回答。一旦技能被预测激活,客户端就会拥有一个预测窗口(prediction window),在其中所产生的预测副作用(side effects)将不会明确地询问服务器。例如,我们不会直接询问:我能减少魔法值吗?我能将这个技能设置成冷却中吗?。这些动作会被认为跟技能的激活在逻辑上是原子操作(logically atomic )。
AbilitySystemComponent提供了一系列的函数来帮助客户端和服务器之间交流技能的激活:TryActivateAbility -> ServerTryActivateAbility -> ClientActivateAbility(Failed/Succeed).

  1. 客户端侧调用TryActivateAbility,里面会生成新的预测键(FPredictionKey)并且调用ServerTryActivateAbility。
  2. 客户端继续执行,使用前面生成的预测键调用ActivateAbility
  3. 在ActivatAbility调用过程中产生的任何副作用(GE、蒙太奇)都将与前面的预测键进行关联
  4. 服务器会在ServerTryActivateAbility里决定技能是否实际发生,调用ClientActivateAbility(Failed/Succeed)
  5. 如果客户端收到ClientAbilityFailed会立即kill技能,并回滚掉跟之前预测键相关联的副作用(GE、蒙太奇)。
  6. 回滚是通过FPredictionKeyDelegates 以及 FPredictionKey::NewRejectedDelegate/NewCaughtUpDelegate/NewRejectOrCaughtUpDelegate来实现的。

GameplayEffect的预测
GameplayEffect被认为是预测的副作用。

  1. GameplayEffect在客户端侧的应用依赖于一个有效的预测键
  2. 一个GameplayEffect被预测,与之关联的Attributes、 GameplayCues、GameplayTags将被预测
  3. 当FActiveGameplayEffect 被创建的时候,会存储对应的预测键
  4. 瞬间的GameplayEffect会在属性预测里解释
  5. 在服务器侧相同的预测键也会被设置在FActiveGameplayEffect,并且会被复制到客户端
  6. 在客户端侧收到一个网络复制下来的FActiveGameplayEffect并且带有一个有效的预测键的时候,客户端会去检查本地是否有一个ActiveGameplayEffect拥有相同的预测键,如果找到一个匹配的那么我们将不执行’on applied’之类的逻辑,例如GameplayCues。这样就解决了重复执行的问题。但客户端将会短暂的有两个相同的GameplayEffects在我们的ActiveGameplayEffects容器里。
  7. 同时,UAbilitySystemComponent::ReplicatedPredictionKey将会追赶上来然后预测的副作用就会被移除掉。在移除的时候,也会再次去检查预测键来决定是否应该执行相关的移除逻辑。
  8. 客户端侧预测的GE无论服务器侧给出的回复是否决还是接受都会被移除
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传在这里插入图片描述

属性预测
attributes预测的基本思想是只预测相对改变值而不是绝对值。我们不应该去预测我们有90的法力,而是预测减少了10法力,直到服务器确认了我们的预测键。对于瞬时性修改会修改成无限时长的修改直到预测的和解。对于属性同步跟预测造成的覆盖问题,我们可以通过将服务器同步下来的值作为Base Value而不是final value,然后在每次发生属性同步后重新聚合新的Final value。

  1. 我们会把Instant类型的GE当作无限持续时间的GE。相关代码在UAbilitySystemComponent::ApplyGameplayEffectSpecToSelf.
  2. 必须要将attributes的网络同步设置成REPNOTIFY_Always,因客户端会进行预测性的提前修改。
  3. 属性的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.

蒙太奇预测
蒙太奇在预测失败的时候会被停止
在这里插入图片描述


Unsupported / Issues/ Todo

Event没有被显示的复制。
预测Meta Attributes(伤害值、治疗值) vs 真实的attributes(血量)
预测周期性的GameplayEffects

资料推荐

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值