虚幻引擎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()));
	}
	
}
相关推荐
StudyWinter1 小时前
【C++】仿函数和回调函数
开发语言·c++·回调函数·仿函数
君鼎2 小时前
Effective C++ 条款55:熟悉Boost库
c++
Zafir20244 小时前
Qt实现TabWidget通过addTab函数添加的页,页内控件自适应窗口大小
开发语言·c++·qt·ui
阿巴~阿巴~4 小时前
深入解析C++非类型模板参数
开发语言·c++
多吃蔬菜!!!4 小时前
vscode 搭建C/C++开发环境搭建(linux)
linux·c语言·c++
谷宇.4 小时前
【Unity3D实例-功能-拔枪】角色拔枪(三)IK的使用-紧握武器
游戏·unity·c#·unity3d·游戏开发·游戏编程·steam
小指纹6 小时前
河南萌新联赛2025第(六)场:郑州大学
java·开发语言·数据结构·c++·算法
岁忧6 小时前
(nice!!!)(LeetCode 每日一题) 1277. 统计全为 1 的正方形子矩阵 (动态规划)
java·c++·算法·leetcode·矩阵·go·动态规划
咔咔咔的6 小时前
679. 24 点游戏
c++
the sun347 小时前
Reactor设计模式及其在epoll中的应用
linux·运维·服务器·c++