0
点赞
收藏
分享

微信扫一扫

22. UE5 RPG使用MMC根据等级设置血量和蓝量(下)


上一篇,我们实现了玩家角色和敌人的等级的获取,使用MMC的提前工作已经准备完成,那么,这一篇讲一下,如何使用MMC,通过角色等级和体力值设置角色的最大血量。
MMC 全称 Mod Magnitude Calculation,为自定义计算数值的类,可以使用蓝图继承,也可以使用c++继承,在这个项目里面我们使用的c++实现。
它需要我们覆写父类的函数CalculateBaseMagnitude_Implementation(),在内部实现计算并返回,接下来,我们将先实现对等级属性和在AS里的体力属性的获取,然后计算并返回。

创建MMC

打开UE,创建C++类,选择所有类,在里面找到GameplayModeMagnitudeCalculation类作为基类

22. UE5 RPG使用MMC根据等级设置血量和蓝量(下)_ue5


创建类,放到一个单独的文件夹,后续我们可能需要制作很多的MMC

22. UE5 RPG使用MMC根据等级设置血量和蓝量(下)_java_02


添加完成后,就可以将UE关闭,在编辑器内编写MMC代码了。

打开首先添加一个构造函数,我们需要在构造函数内去设置需要获取的AS属性

public:
	UMMC_MaxHealth();

我们需要覆盖父类的CalculateBaseMagnitude_Implementation(const FGameplayEffectSpec& Spec),这个函数返回了一个应用此MMC的GE的实例,我们可以通过Spec去获取需要的内容,然后计算数值。

virtual float CalculateBaseMagnitude_Implementation(const FGameplayEffectSpec& Spec) const override;

创建一个FGameplayEffectAttributeCaptureDefinition 属性,我们会在cpp文件内,使用它去获取AS内的体力的值。

private:

	FGameplayEffectAttributeCaptureDefinition VigorDef;

以下为.h文件的代码

// 版权归暮志未晚所有。

#pragma once

#include "CoreMinimal.h"
#include "GameplayModMagnitudeCalculation.h"
#include "MMC_MaxHealth.generated.h"

/**
 * 
 */
UCLASS()
class AURA_API UMMC_MaxHealth : public UGameplayModMagnitudeCalculation
{
	GENERATED_BODY()

public:
	UMMC_MaxHealth();

	virtual float CalculateBaseMagnitude_Implementation(const FGameplayEffectSpec& Spec) const override;

private:

	FGameplayEffectAttributeCaptureDefinition VigorDef;
};

接着转到cpp文件内,编写构造函数,设置需要拾取的参数的内容,用于拾取目标身上的属性的值。

UMMC_MaxHealth::UMMC_MaxHealth()
{
	VigorDef.AttributeToCapture = UAttributeSetBase::GetVigorAttribute(); //设置需要获取的属性对象
	VigorDef.AttributeSource = EGameplayEffectAttributeCaptureSource::Target; //设置拾取对象为GE的应用目标
	VigorDef.bSnapshot = false;

	RelevantAttributesToCapture.Add(VigorDef); //添加到捕获属性数值,只有添加到列表,才会去获取属性值
}

接下来,就是编写CalculateBaseMagnitude_Implementation()函数,我们首先要实现对体力值的获取。获取使用到的函数是GetCapturedAttributeMagnitude(),里面需要FAggregatorEvaluateParameters 参数,那么我们先创建此参数,并设置目标和源的Tag设置给它

//  从 source 和 target 获取 Tag
	const FGameplayTagContainer* SourceTags = Spec.CapturedSourceTags.GetAggregatedTags();
	const FGameplayTagContainer* TargetTags = Spec.CapturedTargetTags.GetAggregatedTags();

	FAggregatorEvaluateParameters EvaluateParameters;
	EvaluateParameters.SourceTags = SourceTags;
	EvaluateParameters.TargetTags = TargetTags;

	float Vigor = 0.f;
	GetCapturedAttributeMagnitude(VigorDef, Spec, EvaluateParameters, Vigor);
	Vigor = FMath::Max<float>(Vigor, 0.f);

体力获取到了,我们还需要获取它的等级,获取等级需要此GE的应用源,可以通过Spec.GetContext().GetSourceObject()去获取源对象,当然,你不设置是获取不到的,这个需要在应用GE的时候,设置源,设置方法如下

void ACharacterBase::ApplyEffectToSelf(TSubclassOf<UGameplayEffect> GameplayEffectClass, float Level) const
{
	check(IsValid(GetAbilitySystemComponent()));
	check(GameplayEffectClass);
	
	FGameplayEffectContextHandle ContextHandle = GetAbilitySystemComponent()->MakeEffectContext();
	ContextHandle.AddSourceObject(this); //设置源对象,可以通过Spec.GetContext().GetSourceObject()去获取源对象
	const FGameplayEffectSpecHandle SpecHandle = GetAbilitySystemComponent()->MakeOutgoingSpec(GameplayEffectClass, Level, ContextHandle);
	GetAbilitySystemComponent()->ApplyGameplayEffectSpecToTarget(*SpecHandle.Data.Get(), GetAbilitySystemComponent());
}

能获取到应用GE的对象,那么,也就是玩家角色自身,我们就可以从玩家角色身上调用GetPlayerLevel()函数获取等级

//获取等级
	ICombatInterface* CombatInterface = Cast<ICombatInterface>(Spec.GetContext().GetSourceObject());
	const int32 Level = CombatInterface->GetPlayerLevel();

体力和等级我们都已经拿到,那么,应用我们自身的公式,得出最大血量结果

//计算最大血量
	return 80.f + Vigor * 2.5f + Level * 10.f;

以下为cpp的完整代码

// 版权归暮志未晚所有。


#include "AbilitySystem/ModMagCalc/MMC_MaxHealth.h"

#include "AbilitySystem/AttributeSetBase.h"
#include "Interaction/CombatInterface.h"

UMMC_MaxHealth::UMMC_MaxHealth()
{
	VigorDef.AttributeToCapture = UAttributeSetBase::GetVigorAttribute(); //设置需要获取的属性对象
	VigorDef.AttributeSource = EGameplayEffectAttributeCaptureSource::Target; //设置拾取对象为GE的应用目标
	VigorDef.bSnapshot = false;

	RelevantAttributesToCapture.Add(VigorDef); //添加到捕获属性数值,只有添加到列表,才会去获取属性值
}

float UMMC_MaxHealth::CalculateBaseMagnitude_Implementation(const FGameplayEffectSpec& Spec) const
{
	//  从 source 和 target 获取 Tag
	const FGameplayTagContainer* SourceTags = Spec.CapturedSourceTags.GetAggregatedTags();
	const FGameplayTagContainer* TargetTags = Spec.CapturedTargetTags.GetAggregatedTags();

	FAggregatorEvaluateParameters EvaluateParameters;
	EvaluateParameters.SourceTags = SourceTags;
	EvaluateParameters.TargetTags = TargetTags;

	//获取体力值
	float Vigor = 0.f;
	GetCapturedAttributeMagnitude(VigorDef, Spec, EvaluateParameters, Vigor);
	Vigor = FMath::Max<float>(Vigor, 0.f);

	//获取等级
	ICombatInterface* CombatInterface = Cast<ICombatInterface>(Spec.GetContext().GetSourceObject());
	const int32 Level = CombatInterface->GetPlayerLevel();

	//计算最大血量
	return 80.f + Vigor * 2.5f + Level * 10.f;
}

编写完成以后,就可以进行编译,进入UE中设置,type修改为Custom Calculation Class,Class设置上我们刚才制作的MMC

22. UE5 RPG使用MMC根据等级设置血量和蓝量(下)_#include_03


完成以后运行,查看效果,我们等级现在设置的是1, Vigor是23 那么结果就应该是 80 + 23*2.5 + 1 * 10 = 147.5,数值可以对起来

22. UE5 RPG使用MMC根据等级设置血量和蓝量(下)_#include_04


打个断点,看一下值,没有问题

22. UE5 RPG使用MMC根据等级设置血量和蓝量(下)_数据库_05


这里,我们就实现了对最大血量的设置。

接下来,按照同样的道理,我们再创建一个MMC_MaxMana用于处理最大蓝量,这里我就不再赘述了,和最大血量一个道理,直接贴代码。

// 版权归暮志未晚所有。

#pragma once

#include "CoreMinimal.h"
#include "GameplayModMagnitudeCalculation.h"
#include "MMC_MaxMana.generated.h"

/**
 * 
 */
UCLASS()
class AURA_API UMMC_MaxMana : public UGameplayModMagnitudeCalculation
{
	GENERATED_BODY()

public:
	UMMC_MaxMana();

	virtual float CalculateBaseMagnitude_Implementation(const FGameplayEffectSpec& Spec) const override;

private:

	FGameplayEffectAttributeCaptureDefinition IntelligenceDef;
	
};

// 版权归暮志未晚所有。


#include "AbilitySystem/ModMagCalc/MMC_MaxMana.h"

#include "AbilitySystem/AttributeSetBase.h"
#include "Interaction/CombatInterface.h"

UMMC_MaxMana::UMMC_MaxMana()
{
	IntelligenceDef.AttributeToCapture = UAttributeSetBase::GetIntelligenceAttribute(); //设置需要获取的属性对象
	IntelligenceDef.AttributeSource = EGameplayEffectAttributeCaptureSource::Target; //设置拾取对象为GE的应用目标
	IntelligenceDef.bSnapshot = false;

	RelevantAttributesToCapture.Add(IntelligenceDef); //添加到捕获属性数值,只有添加到列表,才会去获取属性值
}

float UMMC_MaxMana::CalculateBaseMagnitude_Implementation(const FGameplayEffectSpec& Spec) const
{
	//  从 source 和 target 获取 Tag
	const FGameplayTagContainer* SourceTags = Spec.CapturedSourceTags.GetAggregatedTags();
	const FGameplayTagContainer* TargetTags = Spec.CapturedTargetTags.GetAggregatedTags();

	FAggregatorEvaluateParameters EvaluateParameters;
	EvaluateParameters.SourceTags = SourceTags;
	EvaluateParameters.TargetTags = TargetTags;

	//获取体力值
	float Intelligence = 0.f;
	GetCapturedAttributeMagnitude(IntelligenceDef, Spec, EvaluateParameters, Intelligence);
	Intelligence = FMath::Max<float>(Intelligence, 0.f);

	//获取等级
	ICombatInterface* CombatInterface = Cast<ICombatInterface>(Spec.GetContext().GetSourceObject());
	const int32 Level = CombatInterface->GetPlayerLevel();

	//计算最大血量
	return 50.f + Intelligence * 2.5f + Level * 15.f;
}

智力为21 等级为1 50 + 21 * 2.5f + 15 = 117.5 数值正确。

22. UE5 RPG使用MMC根据等级设置血量和蓝量(下)_数据库_06


上面就是MMC的创建。

初始化血量和蓝量

在设置完最大血量和最大蓝量后,我们会发现血量和蓝量的都是不满的,接下来,我们要将药瓶填满。

22. UE5 RPG使用MMC根据等级设置血量和蓝量(下)_#include_07


在角色基类上面,我们已经完成对PrimaryAttribute和SecondaryAttribute的初始化

22. UE5 RPG使用MMC根据等级设置血量和蓝量(下)_ue5_08


我们在下面接着增加一个参数配置,可以配置更多一个GE

UPROPERTY(BlueprintReadOnly, EditAnywhere, Category="Attributes")
	TSubclassOf<UGameplayEffect> DefaultVitalAttributes;

在应用GE时,也应用到自身,注意顺序,不能乱

void ACharacterBase::InitializeDefaultAttributes() const
{
	ApplyEffectToSelf(DefaultPrimaryAttributes, 1.f);
	ApplyEffectToSelf(DefaultSecondaryAttributes, 1.f);
	ApplyEffectToSelf(DefaultVitalAttributes, 1.f);
}

接着创建第三个初始化GE,我们这次使用Instant,在设置完成最大血量和最大蓝量,血量和蓝量填满即可

22. UE5 RPG使用MMC根据等级设置血量和蓝量(下)_java_09


这里只需要使用Attribute Based 基于最大血量和蓝量一比一填入即可

22. UE5 RPG使用MMC根据等级设置血量和蓝量(下)_#include_10


将GE设置到角色身上

22. UE5 RPG使用MMC根据等级设置血量和蓝量(下)_java_11


药瓶满了

22. UE5 RPG使用MMC根据等级设置血量和蓝量(下)_lua_12


可以看到最大血量和血量,最大蓝量和蓝量数值相同了

22. UE5 RPG使用MMC根据等级设置血量和蓝量(下)_java_13


举报

相关推荐

0 条评论