一、关于GameplayEffectExecutionCalculation类
1、查看GameplayEffectExecutionCalculation类的Execute函数
这个函数将编辑器里设置的参数传进来,然后通过计算再返回出去,这个函数被标记为BlueprintNativeEvent,所以我们可以在自己的类PlayerEffectExecutionCalculation里实现Execute_Implementation函数来计算属性。
2、查看GameplayEffectExecutionCalculation类的帮助宏
DECLARE_ATTRIBUTE_CAPTUREDEF:帮助我们声明要修改的属性指针和捕获的属性变量,例如传入的P是Attack时,使用该宏就有FProperty* AttackProperty指针和FGameplayEffectAttributeCaptureDefinition AttackDef对象
DEFINE_ATTRIBUTE_CAPTUREDEF:帮助我们初始化上面的变量,其中
S:表示属性所属的类
P:表示属性名
T:有Source(当前类的自身属性)和Target(其他类的属性)
B:bool变量,表示是快照还是时拿时取
二、修改C++类BaseAttributeSet,新增攻击力、护甲值等属性
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "BaseAttributeSet")
FGameplayAttributeData Attack;//攻击力
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "BaseAttributeSet")
FGameplayAttributeData Armor;//护甲值
三、创建C++类继承自GameplayEffectExecutionCalculation,命名为PlayerEffectExecutionCalculation
1、PlayerEffectExecutionCalculation.h
#pragma once
#include "CoreMinimal.h"
#include "GameplayEffectExecutionCalculation.h"
#include "PlayerEffectExecutionCalculation.generated.h"
/**
*
*/
UCLASS()
class GASINTRO_API UPlayerEffectExecutionCalculation : public UGameplayEffectExecutionCalculation
{
GENERATED_BODY()
public:
UPlayerEffectExecutionCalculation();
//宏声明
DECLARE_ATTRIBUTE_CAPTUREDEF(Attack)
DECLARE_ATTRIBUTE_CAPTUREDEF(Armor)
DECLARE_ATTRIBUTE_CAPTUREDEF(Health)
void Execute_Implementation(const FGameplayEffectCustomExecutionParameters& ExecutionParams, FGameplayEffectCustomExecutionOutput& OutExecutionOutput) const;
};
注意:
在头文件里使用父类的宏DECLARE_ATTRIBUTE_CAPTUREDEF来声明要修改的属性
并且声明了Execute_Implementation函数,父类里的Execute会执行这里的C++代码
2、PlayerEffectExecutionCalculation.cpp
#include "PlayerEffectExecutionCalculation.h"
#include "BaseAttributeSet.h"
UPlayerEffectExecutionCalculation::UPlayerEffectExecutionCalculation()
{
//宏定义
DEFINE_ATTRIBUTE_CAPTUREDEF(UBaseAttributeSet, Attack, Target, true)
DEFINE_ATTRIBUTE_CAPTUREDEF(UBaseAttributeSet, Armor, Target, true)
DEFINE_ATTRIBUTE_CAPTUREDEF(UBaseAttributeSet, Health, Target, true)
//添加到捕获列表
RelevantAttributesToCapture.Add(AttackDef);
RelevantAttributesToCapture.Add(ArmorDef);
RelevantAttributesToCapture.Add(HealthDef);
}
void UPlayerEffectExecutionCalculation::Execute_Implementation(const FGameplayEffectCustomExecutionParameters& ExecutionParams, FGameplayEffectCustomExecutionOutput& OutExecutionOutput) const
{
//计算捕获的属性
float AttackMagnitude, ArmorMagnitude = 0.0f;
ExecutionParams.AttemptCalculateCapturedAttributeMagnitude(AttackDef, FAggregatorEvaluateParameters(), AttackMagnitude);
ExecutionParams.AttemptCalculateCapturedAttributeMagnitude(ArmorDef, FAggregatorEvaluateParameters(), ArmorMagnitude);
//计算最终伤害
float FinalDamage = FMath::Clamp(AttackMagnitude - ArmorMagnitude, 0.0f, AttackMagnitude - ArmorMagnitude);
OutExecutionOutput.AddOutputModifier(FGameplayModifierEvaluatedData(HealthProperty, EGameplayModOp::Additive, -FinalDamage));
}
注意:
首先,cpp文件在构造函数中使用宏DEFINE_ATTRIBUTE_CAPTUREDEF来初始化要修改的属性
因为我们要修改的属性属于UBaseAttributeSet而非当前类自身,所以得传Target
其次,将AttackDef等属性添加到捕获列表RelevantAttributesToCapture中,这里的AttackDef就是头文件中的宏定义帮我们声明好的。
然后,在Execute_Implementation里实现具体的计算方法,其中的AttemptCalculateCapturedAttributeMagnitude方法如下:
第一个参数传入捕获的属性AttackDef
第二个参数是FAggregatorEvaluateParameters类型,一般是用作BUFF计算或者其他更复杂的计算,我们暂时没有用到,所以传个默认值就行
第三个参数是计算后的输出值
最后,通过AddOutputModifier输出计算结果,计算结果要封装成FGameplayModifierEvaluatedData类型,例如FGameplayModifierEvaluatedData(HealthProperty, EGameplayModOp::Additive, -FinalDamage)就表示:修改生命值属性,计算方式为加法,加上一个负的最终伤害值
三、在UE中配置上面自定义的GameplayEffectExecution
1、打开GE_MeleeAttack_Damage进行如下修改
可以发现,之前的文章里使用的是Modifiers来修改角色生命值属性,这次我们改用Executions来算上角色的护甲,并覆盖了角色的生命值。
2、别忘了添加Tag
至此,就完成了角色攻击敌人时,敌人会扣掉(角色攻击力-角色护甲)的血量。
PS:实际上应该用角色攻击-敌人护甲,这里为了方便测试。