虚幻引擎5 GAS开发俯视角RPG游戏 #06-11:游戏后效果执行

本文介绍了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()));
	}
	
}
相关推荐
Peter·Pan爱编程25 分钟前
14. Lambda 表达式:随手可写的函数对象
c++·算法·ai编程
不想写代码的星星1 小时前
从分支预测角度看 C++:为什么你的热循环慢得离谱?
c++
郝学胜-神的一滴1 小时前
Qt 高级开发 018:复刻经典登录界面布局与窗口美化全解析
开发语言·c++·qt·程序人生·用户界面
郝亚军2 小时前
IEEE 754 单精度浮点的SEM表示
开发语言·c++·算法
Yyyyyy~3 小时前
【C++】数组篇
开发语言·c++
qq_333120973 小时前
C++高并发内存池的整体设计和实现思路_C 语言
java·c语言·c++
牛肉在哪里3 小时前
ros2 从零开始27 编写广播C++
开发语言·c++·机器人
Curvatureflight3 小时前
前端国际化 i18n 落地实践:语言包、动态文案和格式化问题怎么处理?
前端·c++·vue
黄小白的进阶之路4 小时前
C++提高编程---3.9 STL-常用容器-map/multimap 容器【P231~P235】
c++
WBluuue4 小时前
Codeforces 1096 Div3(ABCDEFGH)
c++·算法