4.3 属性 - Attributes

4.3.1 属性的定义 - Attribute Definition

Attribute是由结构体FGameplayAttributeData定义的一系列浮点值。它们能够表示角色拥有的生命值、角色等级以及药水的充能数等等。只要是从属于Actor的游玩相关的数值,就可以考虑将其设为一项AttributeAttribute通常应该由GameplayEffect来负责修改,这样ASC就能够predict预测相应的变化。

Attributes是由AttributeSet来进行定义的并保存在其中。AttributeSet负责处理那些被标记要进行复制的Attributes。参考AttributeSets的相关小节,来获取更多关于如何定义Attributes的内容。

小贴士: 如果你不想要某个Attribute显示在编辑器的Attributes列表中,可以使用Meta = (HideInDetailsView)这样的属性说明符(Property Specifier)。

4.3.2 基本值和当前值 - BaseValue vs CurrentValue

每个属性Attribute都由两个值组成——基本值BaseValue和当前值CurrentValueBaseValueAttribute的一个恒定值,而CurrentValue则是BaseValue再叠加上来自GameplayEffects的临时修改后的结果。例如,你的Character可能会有一个移动速度Attribute,其BaseValue为600u/s(译者注:单位虚幻距离每秒)。此时还没有施加任何的影响移动速度相关的GameplayEffectsCurrentValue也就还是600u/s。如果角色被施加了一个50u/s的移速buff,BaseValue还仍然是600u/s,而CurrentValue此时则是600 + 50 = 650u/s。当移速的buff消失后吗,CurrentValue会恢复到BaseValue的值,也就是600u/s。

GAS的新手经常会把BaseValueAttribute的最大值搞混,把两者当作同一个东西。这种认知并不正确。Attributes的最大值也会发生改变,它会和技能或者UI相关联,应该作为一个单独的Attributes来处理。对于硬编码的最大值和最小值,有一种方式可以通过FAttributeMetaDataDataTable来定义(其中有关于最大值和最小值设置的内容),但是Epic对于这个结构体注释道:work in progress,也就是该功能目前还没有稳定下来,可能还会进行修改。详细内容请参阅AttributeSet.h。为了防止混淆,我建议是将那些和技能或者UI关联的最大值作为一个单独的Attributes来对待——硬编码的最大值和最小值仅用于限定AttributeSet中的Attributes的上下限的限定。Attributes的上下限的限制的讨论后面还会继续进行,具体是在GameplayEffects为属性施加影响时,比如PreAttributeChange()中对CurrentValue可以发生的变化的限制,又比如PostGameplayEffectExecute()中对BaseValue可以发生的变化的限制。

即刻生效InstantGameplayEffects会对BaseValue产生永久性的影响,而持续一段时间Duration的和无限持续InfiniteGameplayEffects改变的是CurrentValue。周期性PeriodicGameplayEffectsinstant类型的GameplayEffects是类似的,都改变的是BaseValue

4.3.3 元属性 - Meta Attributes

一些Attributes会作为和其他Attributes作交互的临时值的占位数据,这一类的属性被称为是元属性Meta Attributes。例如,我们通常会去将伤害值定义为Meta Attribute。我们使用伤害值的Meta Attribute作为占位数据,而不是使用GameplayEffect直接改变我们的生命值的Attribute。这样,伤害值就可以通过 GameplayEffectExecutionCalculation中的buff和debuff等进行修改,也可以在AttributeSet中作进一步处理,例如让伤害值减去当前的护甲的Attribute,然后再让生命值的Attribute减去前面的结果。伤害值的Meta Attribute在多个GameplayEffects之间并不是恒定的,可以被任意一个覆盖重写。Meta Attributes通常不会被复制。

像我们经常会说:“我造成了多少的伤害”,“这个伤害值怎么处理”之类的,Meta Attributes为此(伤害和治疗这类的属性)提供了一个良好的逻辑分离。这里的逻辑分离意思是我们的Gameplay EffectsExecution Calculations并不需要知道目标是如何处理这个伤害值的。继续我们关于伤害的话题,Gameplay Effect决定了伤害值的多少,然后AttributeSet去具体处理这个值。并不是所有的角色都有着相同的Attributes,特别是当你拓展AttributeSets的子类时。基类AttributeSet可能仅有生命值一个Attribute,其子类可能添加了一个护盾的Attribute。那自然的,基类和子类在处理这个伤害值的时候就不同了。

即便Meta Attributes是一个良好的设计模式,但是这并不意味着非得用它不可。如果你仅有一个Execution Calculation用来处理所有的伤害值,且所有角色共享着同一个Attribute Set,那么你就可以直接在Execution Calculation中来作伤害值、生命值和护盾值的计算和修改。这样做的代价自然就是牺牲掉一定的灵活性,这中间的权衡全在于你。

4.3.4 响应属性的变化 - Responding to Attribute Changes

要监听某个Attribute的变化从而更新UI或者其他游玩部分,可以使用UAbilitySystemComponent::GetGameplayAttributeValueChangeDelegate(FGameplayAttribute Attribute)。这个方法返回一个委托,你可以自由绑定相应的回调,当对应的Attribute发生变化时就会自动执行这个回调。这个委托提供了一个FOnAttributeChangeData参数,有NewValueOldValue以及FGameplayEffectModCallbackData注意:FGameplayEffectModCallbackData只能够在服务器进行设置。

AbilitySystemComponent->GetGameplayAttributeValueChangeDelegate(AttributeSetBase->GetHealthAttribute()).AddUObject(this, &AGDPlayerState::HealthChanged);
virtual void HealthChanged(const FOnAttributeChangeData& Data);

示例项目将Attribute值变化的委托绑定到GDPlayerState中的一个方法来更新HUD并响应玩家的死亡(生命值归零)的情况。

在示例项目中还包含一个使用异步任务ASyncTask将所有这些封装起来的自定义蓝图节点。它被用在名为UI_HUDUMG Widget用来更新生命值,魔法值以及体力值。这个AsyncTask会一直存在直到手动调用了EndTask(),我们一般会在UMG WidgetDestruct事件中去调用。参阅AsyncTaskAttributeChanged.h/cpp获取更多内容。

Listen for Attribute Change BP Node

4.3.5 衍生属性 - Derived Attributes

要令某个Attribute的值是从其他某个或者某些Attributes的值衍生过来,需要使用Infinite类型的GameplayEffect,以及一个或多个Attribute Based或者MMCModifiersDerived Attribute将会自动根据其依赖的Attribute的更新而进行更新。

Derived Attribute上的所有Modifiers的最终公式与Modifier Aggregators的公式是同一个。如果你需要依照一定的顺序进行计算,需要在MMC内完成所有的操作。

((CurrentValue + Additive) * Multiplicitive) / Division

注意: 如果在PIE中运行多个客户端时,你需要在编辑器偏好界面中禁用Run Under One Process,否则处第一个客户端以外的其他客户端将不会更新Derived Attributes

这里我们举个例子,我们有一个Infinite类型的GameplayEffect,其会根据TestAttrBTestAttrC的值来推导TestAttrA的值。公式具体为TestAttrA = (TestAttrA + TestAttrB) * ( 2 * TestAttrC)。无论何时,当TestAttrBTestAttrC中的任意一个属性更新时,那么TestAttrA将会自动根据上面的公式进行计算。

Derived Attribute Example

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值