UE GAS笔记
UE_GAS笔记
1.ASC及其初始化
声明成员变量 AbilitySystemComponent
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "GAS|Abilities")
class UASC* AbilitySystemComponent;
构造函数
ASC
一般在OwnerActor
的构建函数中创建并且需要明确标记为Replicated. 这必须在C++中完成.
AbilitySystemComponent = CreateDefaultSubobject<UASC>(TEXT("AbilitySystem"));
AbilitySystemComponent->SetIsReplicated(true);
设置ASC同步模式
AbilitySystemComponent->SetReplicationMode(EGameplayEffectReplicationMode::Full);
同步模式 | 何时使用 | 描述 |
---|---|---|
Full | 单人 | 所有GameplayEffect 都同步到客户端. |
Mixed | 多人, 玩家控制的Actor | GameplayEffect 只同步到其所属客户端, 只有GameplayTag 和GameplayCue 同步到所有客户端. |
Minimal | 多人, AI控制的Actor | GameplayEffect 从不同步到任何客户端, 只有GameplayTag 和GameplayCue 同步到所有客户端. |
- 由此可见,如果想要在客户端拿到GE的信息,必须将ASC的复制模式设置为Full
重载GetAbilitySystemComponent()函数
-
该接口有一个必须重写的函数,
UAbilitySystemComponent* GetAbilitySystemComponent() const
, 其返回一个指向ASC
的指针,ASC
通过寻找该接口函数来和系统内部进行交互.//.h virtual UAbilitySystemComponent* GetAbilitySystemComponent() const override;
//.cpp UAbilitySystemComponent* Character::GetAbilitySystemComponent() const { return AbilitySystemComponent; }
-
初始化ASC
//ASC在服务端和客户端上均需初始化 //void UASC_honkai_rts::InitAbilityActorInfo(AActor *InOwnerActor, AActor *InAvatarActor) AbilitySystemComponent->InitAbilityActorInfo(this, this);
2.AS
创建和初始化AS
- 派生自UAttributeSet,在OwnerActor的构造函数中创建
AttributeSet
会自动注册到其ASC
. 这必须在C++中完成. FGameplayAttributeData
拥有两个值BaseValue,CurrentValue- 当GE的延时策略为
instant
时,永久性的修改BaseValue
,持续(Has Duration)
和无限(Infinite)
可以修改CurrentValue.
- 当GE的延时策略为
- 当GE为周期(Periodic)时,视为
instant
,永久修改BaseValue
监听AS改变
定义AS
-
Attribute只能使用C++在AttributeSet头文件中定义.
-
建议把下面这个宏块加到每个
AttributeSet
头文件的顶部, 其会自动为每个Attribute
生成getter和setter函数. -
#define ATTRIBUTE_ACCESSORS(ClassName, PropertyName) \ GAMEPLAYATTRIBUTE_PROPERTY_GETTER(ClassName, PropertyName) \ GAMEPLAYATTRIBUTE_VALUE_GETTER(PropertyName) \ GAMEPLAYATTRIBUTE_VALUE_SETTER(PropertyName) \ GAMEPLAYATTRIBUTE_VALUE_INITTER(PropertyName)
-
举例
-
在AS中声明FGameplayAttributeData变量
-
UPROPERTY(BlueprintReadOnly, Category = "Health", ReplicatedUsing = OnRep_Health) FGameplayAttributeData Health; ATTRIBUTE_ACCESSORS(UGDAttributeSetBase, Health)
-
-
在头文件中定义OnRep函数:
-
UFUNCTION() virtual void OnRep_Health(const FGameplayAttributeData& OldHealth);
-
-
用预测系统(Prediction System)使用的
GAMEPLAYATTRIBUTE_REPNOTIFY
宏填充OnRep函数:-
void UGDAttributeSetBase::OnRep_Health(const FGameplayAttributeData& OldHealth) { GAMEPLAYATTRIBUTE_REPNOTIFY(UGDAttributeSetBase, Health, OldHealth); }
-
-
Attribute
需要添加到GetLifetimeReplicatedProps
:-
void UGDAttributeSetBase::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const { Super::GetLifetimeReplicatedProps(OutLifetimeProps); //REPTNOTIFY_Always用于设置OnRep函数在客户端值已经与服务端同步的值相同的情况下触发(因为有预测), 默认设置下, 客户端值与服务端同步的值相同时, OnRep函数是不会触发的. DOREPLIFETIME_CONDITION_NOTIFY(UGDAttributeSetBase, Health, COND_None, REPNOTIFY_Always); }
-
-
建议使用instant的GE来初始化AS
AS主要重载函数
PreAttributeChange(const FGameplayAttribute& Attribute, float& NewValue)
是AttributeSet
中的主要函数之一, 其在修改发生前响应Attribute
的CurrentValue变化, 其是通过引用参数NewValue限制(Clamp)CurrentValue即将进行的修改的理想位置.- 这个时间点为:对
Attribute
的修改已经发生, 但是还没有被同步回客户端,客户端只会收到函数作用后的值.
- 这个时间点为:对
PostGameplayEffectExecute(const FGameplayEffectModCallbackData & Data)
仅在即刻(Instant)GameplayEffect
对Attribute
的BaseValue修改之后触发, 当GameplayEffect对其修改时, 这就是一个处理更多Attribute
操作的有效位置.- 例如用于AS变动的连带效应,比如伤害值作用于护盾值,当护盾值不足以抵消伤害时,便作用于生命值。
OnAttributeAggregatorCreated(const FGameplayAttribute& Attribute, FAggregator* NewAggregator)
会在Aggregator为集合中的某个Attribute
创建时触发
3.Gameplay Effects
定义GE
关于其中出现的Require Tags和Ignore Tags的更好的理解方法:把它理解为一个布尔判断器,Require为And,Ignore为Not,只有Require中的Tag全部存在,Ignore中的Tag没有一个存在时,判断通过,才可执行。
在GE中所说的parent即被应用此GE的ASC组件
-
GE是Ability修改其自身和其他AS和GameplayTag的容器, 其可以立即修改
Attribute
(像伤害或治疗)或应用长期的状态buff/debuff(像移动速度加速或眩晕). UGameplayEffect只是一个定义单一游戏效果的数据类, 不应该在其中添加额外的逻辑.
DurationPolicy延时策略
-
类型 GameplayCue事件 何时使用 即刻(Instant) Execute 对 Attribute
中BaseValue立即进行的永久性修改. 其不会应用GameplayTag
, 哪怕是一帧.持续(Duration) Add & Remove 对 Attribute
中CurrentValue的临时修改和当GameplayEffect
终止或手动移除时, 应用将要被移除的GameplayTag
. 持续时间是在UGameplayEffect类/蓝图中明确的.无限(Infinite) Add & Remove 对 Attribute
中CurrentValue的临时修改和当GameplayEffect
移除时, 应用将要被移除的GameplayTag
. 该类型自身永不终止且必须由某个Ability或ASC
手动移除. -
持续(Duration)
和无限(Infinite)
GE可以选择应用周期性的Effect, 其每过X秒(由周期定义)就应用一次Modifier
和Execution
, 当周期性的Effect修改Attribute
的BaseValue和执行GameplayCue
时就被视为即刻(Instant)GameplayEffect
。
Modifier修改器
-
GameplayEffect
通过Modifier和Execution修改Attribute
-
-
Modifier
可以修改Attribute
并且是唯一可以预测性修改Attribute
的方法. 一个GameplayEffect
可以有0个或多个Modifier
, 每个Modifier
通过某个指定的操作只能修改一个Attribute
.-
ModifierOp:对属性的数值操作
-
操作 描述 备注 Add 将 Modifier
指定的Attribute
加上计算结果. 使用负数以实现减法操作.Multiply 将 Modifier
指定的Attribute
乘以计算结果.对于基于百分比的修改, 确保使用 Multiply
操作以使其在加法操作之后.Divide 将 Modifier
指定的Attribute
除以计算结果.Override 使用计算结果覆盖 Modifier
指定的Attribute
.Override Modifier
会优先覆盖最后应用的Modifier
得出的最终值.
-
-
有四种类型的
Modifier
:ScalableFloat
,AttributeBased
,CustomCalculationClass
, 和SetByCaller
, 它们全都生成一些浮点数, 用于之后基于各自的操作修改指定Modifier
的Attribute
.-
ModifierMagnitude:修改器的具体数值
-
Modifier类型 描述 Scalable Float FScalableFloat结构体可以指向某个横向为变量, 纵向为等级的Data Table, Scalable Float
会以Ability的当前等级自动读取指定Data Table的某行值(或者在GameplayEffectSpec中重写的不同等级), 该值还可以进一步被系数处理, 如果没有指定Data Table/Row, 那么就会将其视为1, 因此该系数就可以在所有等级都硬编码为一个值.Attribute Based Attribute Based Modifier
将Source(GameplayEffectSpec
的创建者)或Target(GameplayEffectSpec
的接收者)上的CurrentValue或BaseValue视为Backing Attribute
, 可以使用系数和Pre与Post系数和来修改它.Snapshotting
意味着当GameplayEffectSpec
创建时捕获该Attribute
, 而No Snapshotting
意味着当GameplayEffectSpec
应用时捕获该Attribute
.Custom Calculation Class Custom Calculation Class
为复杂的Modifier
提供了最大的灵活性, 该Modifier
使用了ModifierMagnitudeCalculation类, 且可以使用系数和Pre与Post系数和来处理浮点值结果.Set By Caller SetByCaller
Modifier是运行时由Ability或GameplayEffectSpec
的创建者于GameplayEffect
之外设置的值, 例如, 如果你想让伤害值随玩家蓄力技能的长短而变化, 那么就需要使用SetByCaller
.SetByCaller
本质上是存于GameplayEffectSpec
中的TMap<FGameplayTag, float>
,Modifier
只是告知Aggregator
去寻找与提供的GameplayTag
相关联的SetByCaller
值.Modifier
使用的SetByCaller
只能使用该概念的GameplayTag
形式,FName
形式在此处不适用. 如果Modifier
被设置为SetByCaller
, 但是带有正确GameplayTag
的SetByCaller
在GameplayEffectSpec
中不存在, 那么游戏会抛出一个运行时错误并返回0, 这可能在Divide
操作中造成问题. 参阅SetByCallers获取更多关于如何使用SetByCaller
的信息. -
Scalable Float Magnitude:根据值采样曲线值。
-
-
Gameplay Tags
-
源(Source)
ASC
和目标(Target)ASC
的标签都被GameplayEffect
所捕获,- 当
GameplayEffectSpec
创建时, 源(Source)ASC
的标签被捕获. - 当执行Effect时, 目标(Target)
ASC
的标签被捕获. - 当确定
无限(Infinite)
或持续(Duration)
Effect的Modifier
是否满足条件可以被应用(也就是聚合器条件(Aggregator Qualify))并且过滤器已经设置时, 被捕获的标签就会和过滤器进行比对.
- 当
-
-
Immunity免疫
GameplayEffect
可以基于GameplayTag实现免疫, 有效阻止其他GameplayEffect
应用. 尽管免疫可以由Application Tag Requirements
等方式有效地实现, 但是使用该系统可以在GameplayEffect
被免疫阻止时提供UAbilitySystemComponent::OnImmunityBlockGameplayEffectDelegate
委托(Delegate).GrantedApplicationImmunityTags
会检查源(Source)ASC
(包括源Ability的AbilityTag, 如果有的话)是否包含特定的标签, 这是一种基于确定Character或源(Source)的标签对其所有GameplayEffect
提供免疫的方法.Granted Application Immunity Query
会检查传入的GameplayEffectSpec
是否与其查询条件相匹配, 从而阻止或允许其应用.比之GrantedApplicationImmunityTags
功能更为强大,但是速度更慢.
Stacking叠层/堆栈
-
堆栈类型 描述 Aggregate by Source 目标(Target)上的每个源(Source) ASC
都有一个单独的堆栈实例, 每个源(Source)可以应用堆栈中的X个GameplayEffect
.Aggregate by Target 目标(Target)上只有一个堆栈实例而不管源(Source)如何, 每个源(Source)都可以在共享堆栈限制(Shared Stack Limit)内应用堆栈. -
Stack Duration Refresh Policy 堆栈时长刷新策略,每当有任意一个堆叠成功应用时该效果的持续时间就会被刷新.
-
Stack Period Reset Policy 堆栈周期复位策略,任意成功应用的堆叠中,任何向下个tick的
-
Stack Expiration Policy 堆栈结束策略 说明 Clear Entire Stack
清除整个堆栈当GE终止时,清除整个堆栈 Remove single stack and refresh duration
删除单个堆栈并刷新持续时间当前堆栈数量减一,刷新持续时间,该GE不是被重新应用,只是继续存在,少了个堆栈 Refresh Duration
刷新时间GE的持续时间被刷新,这本质上使得GE的持续效果时无限的,可以通过OnStackCountChange手动处理堆栈递减回调
Period周期
-
Periodic Inhibition Policy 周期抑制策略
-
Never Reset 不重置 周期计时将继续,不抑制 Reset Period 重置间隔 重置周期,下次执行将发生在抑制解除后的一个完整周期内 Excute and Reset Period 执行和重置周期 立即执行,重置周期
Expiration 终止
-
Premature Expiration Effect Classes
过早终止应用的效果类该GE提前终止时将会应用的GE(强制移除forced removal,清除标签clear Tags等)只适用于有持续时间的GE Routine Expiration Effect Classes
常规终止时应用的效果类此GE通过其持续时间自然终止时应用的GE,只适用于有持续时间的GE
Application应用
-
Chance To Apply To Target 应用至target的概率 该GE应用于目标角色的概率(0为从不,1为总是) Application Requirement 应用的需要
Overflow溢出
-
Overflow Effects 当一个堆栈效果通过其他尝试应用一个堆栈数量溢出其记数时应用的GE Deny Overflow Application 如果为true,在堆栈记数满时进行的堆栈尝试将失败,导致持续时间和context不被刷新 clear stack on overflow 如果为true,溢出时该GE的整个堆栈将被清除
Cues 显示
-
Require Modifier Success to Trigger Cues 需要修改器成功触发GC 若为true,只有当GE修改器成功应用时(无论是modifier还是execution),GC才会触发 suppress stacking cues 阻止堆栈时触发GC 若为true,GC只会在堆栈GE的首个实例中被触发 Gameplay Cues 该GE触发非模拟反应时响应的GC,如声音,粒子效果等 UI Data 该GE的UI表示的数据,这应该包括文本,图标等内容,server-only构件中不可用
Tags标签
-
combined Tags 组合标签 我继承的标签和我添加的被我移除的减标签 Added 除了我的parent的标签之外我所拥有的标签 Removed 如果我的parent拥有这些标签,就应该删除 -
Gameplay Effect Asset Tag GE资产的标签 该GE所拥有的标签,不给予actor Granted Tags 授予标签 这些标签将应用于我所应用的actor Granted Blocked Ability Tags 授予锁定能力标签 这些锁定的能力标签将应用于我所应用的actor Ongoing Tag Requirements 持续应用该GE的标签要求 一旦应用,这些标签将用于确定GE是打开还是关闭。
一个GE可以关闭,什么都不做,但是任然被应用Application Tag Requirements 应用该GE的标签要求 该GE应用到目标的标签要求,这是应用时的通过/失败。如果失败,表示该GE应用失败 Removal Tag Requirements 拆除该GE的标签要求 如果满足这些标签要求将会移除该GE,也会防止GE应用 Remove Gameplay Effect Query 删除GE查询 在一个GE的应用中,任何与此查询匹配的激活的GE都将被删除。
功能更加强大,但稍慢于Remove Gameplay Effects with TagsRemove Gameplay Effects with Tags
删除带有标签的GE
Granted Abilities
-
Removal Policy 移除策略
-
Cancel Ability Immediately 立即取消能力 激活的能力会被立即取消并移除 Remove Ability on End 激活的能力允许完成,然后被移除 Do Nothing 当授予的GE被移除时,授予的能力将被单独保留
-
应用GameplayEffect
-
GE可以被GA和
ASC
中的多个函数应用, 其通常是ApplyGameplayEffectTo
的形式, 不同的函数本质上都是最终在目标上调用UAbilitySystemComponent::ApplyGameplayEffectSpecToSelf()
的方便函数. -
为了在
GameplayAbility
之外应用GameplayEffect
, 例如对于某个投掷物, 你就需要获取到目标的ASC
并使用它的函数之一来ApplyGameplayEffectToSelf
. -