虚幻引擎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()));
	}
	
}
相关推荐
AI进化营-智能译站10 小时前
ROS2 C++开发系列07-高效构建机器人决策逻辑,运算符与控制流实战
开发语言·c++·ai·机器人
winner888110 小时前
C++ 命名空间、虚函数、抽象类、protected 权限全套通俗易懂精讲(附与 Java 对比)
java·开发语言·c++
不会编程的懒洋洋10 小时前
C# P/Invoke 基础
开发语言·c++·笔记·安全·机器学习·c#·p/invoke
24白菜头11 小时前
【无标题】
c++·笔记·学习·harmonyos
Avalon71211 小时前
Unity3D响应式渲染UI框架UniVue
游戏·ui·unity·c#·游戏引擎
charlie11451419111 小时前
嵌入式C++实践开发第21篇(单片机实践):按钮输入 —— 硬件原理、消抖与HAL API
开发语言·c++·单片机
AKDreamer_HeXY11 小时前
QOJ 12255 - 36 Puzzle 题解
数据结构·c++·数学·算法·icpc·qoj
AI进化营-智能译站11 小时前
ROS2 C++开发系列13-运算符重载让ROS2消息处理更自然
java·开发语言·c++·ai
zhouwy11312 小时前
Poco 与 libevent 网络编程
c++
叼烟扛炮12 小时前
C++第四讲:类和对象(下)
c++·算法·类和对象