本文介绍了GameplayAbilitySystem中PostGameplayEffectExecute函数的实现与应用。该函数在数值变化后触发,主要用于Instant类GameplayEffect(Duration和Infinite类若设置Period也可触发)。文章详细展示了如何通过该函数修正数值(相比PreAttributeChange能真正修改数值),并演示了血量、蓝量等属性的安全范围控制。同时,定义了FEffectProperties结构体封装GE相关对象,提供了SetEffectProperties方法统一处理施放者和目标的对象引用获取,为后续逻辑处理提供便利。这些实现可用于死亡判定、无敌状态等游戏逻辑处理。
1.PostGameplayEffectExecute
PostGameplayEffectExecute()函数是在数值变化后触发的,一般只会在Instant类型的GameplayEffect才可以触发(Duration和Infinite类的GameplayEffect如果设置Period也可以触发)。
并且,我们还可以在这里面去修正数值,(在PreAttributeChange回调里面,只能修正显示的结果,实际结果没有变)。
这个函数的应用场景很多,我们可以做一些逻辑操作,比如死亡,无敌不扣血等等。
Source/CC_Aura/Public/AbilitySystem/CC_AttributeSet.h:
cpp
//属性更改后的方法
virtual void PostGameplayEffectExecute(const struct FGameplayEffectModCallbackData& Data) override;
Source/CC_Aura/Private/AbilitySystem/CC_AttributeSet.cpp:
cpp
void UCC_AttributeSet::PostGameplayEffectExecute(const struct FGameplayEffectModCallbackData& Data)
{
Super::PostGameplayEffectExecute(Data);
if (Data.EvaluatedData.Attribute == GetHealthAttribute())
{
UE_LOG(LogTemp, Warning, TEXT("Health: %f"), GetHealth());
UE_LOG(LogTemp, Warning, TEXT("Magnitude: %f"), Data.EvaluatedData.Magnitude);
}
}
2.接下来,我们将从Data中获取到需要的然后封装成一个结构体,方便后续使用。
Source/CC_Aura/Public/AbilitySystem/CC_AttributeSet.h:
cpp
// 用于存储施放GE的相关对象和目标的相关对象
USTRUCT()
struct FEffectProperties
{
GENERATED_BODY()
FEffectProperties(){}
FGameplayEffectContextHandle EffectContextHandle;
UPROPERTY()
UAbilitySystemComponent* SourceASC = nullptr;
UPROPERTY()
AActor* SourceAvatarActor = nullptr;
UPROPERTY()
AController* SourceController = nullptr;
UPROPERTY()
ACharacter* SourceCharacter = nullptr;
UPROPERTY()
UAbilitySystemComponent* TargetASC = nullptr;
UPROPERTY()
AActor* TargetAvatarActor = nullptr;
UPROPERTY()
AController* TargetController = nullptr;
UPROPERTY()
ACharacter* TargetCharacter = nullptr;
};
3.创建私有函数,给FEffectProperties赋值
Source/CC_Aura/Public/AbilitySystem/CC_AttributeSet.h:
cpp
private:
void SetEffectProperties(const struct FGameplayEffectModCallbackData& Data, FEffectProperties& Props) const;
Source/CC_Aura/Private/AbilitySystem/CC_AttributeSet.cpp:
cpp
void UCC_AttributeSet::SetEffectProperties(const struct FGameplayEffectModCallbackData& Data, FEffectProperties& Props) const
{
Props.EffectContextHandle = Data.EffectSpec.GetContext();
//获取效果所有者的相关对象
Props.SourceASC = Props.EffectContextHandle.GetOriginalInstigatorAbilitySystemComponent(); //获取SourceASC
if(IsValid(Props.SourceASC) && Props.SourceASC->AbilityActorInfo.IsValid() && Props.SourceASC->AbilityActorInfo->AvatarActor.IsValid())
{
Props.SourceAvatarActor = Props.SourceASC->AbilityActorInfo->AvatarActor.Get(); //获取SourceAvatarActor
Props.SourceController = Props.SourceASC->AbilityActorInfo->PlayerController.Get(); //获取SourceController
if(Props.SourceController == nullptr && Props.SourceAvatarActor != nullptr)
{
if(const APawn* Pawn = Cast<APawn>(Props.SourceAvatarActor))
{
Props.SourceController = Pawn->GetController();
}
}
if(Props.SourceController)
{
Props.SourceCharacter = Cast<ACharacter>(Props.SourceController->GetPawn()); //获取SourceCharacter
}
}
if(Data.Target.AbilityActorInfo.IsValid() && Data.Target.AbilityActorInfo->AvatarActor.IsValid())
{
Props.TargetAvatarActor = Data.Target.AbilityActorInfo->AvatarActor.Get();
Props.TargetController = Data.Target.AbilityActorInfo->PlayerController.Get();
Props.TargetCharacter = Cast<ACharacter>(Props.TargetAvatarActor);
Props.TargetASC = UAbilitySystemBlueprintLibrary::GetAbilitySystemComponent(Props.TargetAvatarActor);
}
}
4.将方法添加到PostGameplayEffectExecute函数里:
cpp
void UCC_AttributeSet::PostGameplayEffectExecute(const struct FGameplayEffectModCallbackData& Data)
{
Super::PostGameplayEffectExecute(Data);
FEffectProperties Props;
SetEffectProperties(Data, Props);
if(Data.EvaluatedData.Attribute == GetHealthAttribute())
{
SetHealth(FMath::Clamp(GetHealth(), 0.f, GetMaxHealth()));
}
if(Data.EvaluatedData.Attribute == GetManaAttribute())
{
SetMana(FMath::Clamp(GetMana(), 0.f, GetMaxMana()));
}
}