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

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

创建MMC

打开UE,创建C++类,选择所有类,在里面找到GameplayModeMagnitudeCalculation类作为基类
在这里插入图片描述
创建类,放到一个单独的文件夹,后续我们可能需要制作很多的MMC
在这里插入图片描述
添加完成后,就可以将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 获取 Tagconst 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 获取 Tagconst 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
在这里插入图片描述
完成以后运行,查看效果,我们等级现在设置的是1, Vigor是23 那么结果就应该是 80 + 23*2.5 + 1 * 10 = 147.5,数值可以对起来
在这里插入图片描述
打个断点,看一下值,没有问题
在这里插入图片描述
这里,我们就实现了对最大血量的设置。
接下来,按照同样的道理,我们再创建一个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 获取 Tagconst 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 数值正确。
在这里插入图片描述
上面就是MMC的创建。

初始化血量和蓝量

在设置完最大血量和最大蓝量后,我们会发现血量和蓝量的都是不满的,接下来,我们要将药瓶填满。
在这里插入图片描述
在角色基类上面,我们已经完成对PrimaryAttribute和SecondaryAttribute的初始化
在这里插入图片描述
我们在下面接着增加一个参数配置,可以配置更多一个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,在设置完成最大血量和最大蓝量,血量和蓝量填满即可
在这里插入图片描述
这里只需要使用Attribute Based 基于最大血量和蓝量一比一填入即可
在这里插入图片描述
将GE设置到角色身上
在这里插入图片描述
药瓶满了
在这里插入图片描述
可以看到最大血量和血量,最大蓝量和蓝量数值相同了
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/758726.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于springboot的同城宠物帮养照看平台

技术&#xff1a;springbootmysqlvue 一、背景 如今社会上各行各业&#xff0c;都喜欢用自己行业的专属软件工作&#xff0c;互联网发展到这个时候&#xff0c;人们已经发现离不开了互联网。新技术的产生&#xff0c;往往能解决一些老技术的弊端问题。因为传统同城上门喂遛宠物…

Java学习六—面向对象

一、关于面向对象 1.1简介 Java 是一种面向对象编程语言&#xff0c;其核心思想是面向对象编程&#xff08;Object-Oriented Programming&#xff0c;OOP&#xff09;。 面向对象编程是一种程序设计范式&#xff0c;它将数据与操作数据的方法&#xff08;函数&#xff09;捆…

软件工程-第三版王立福-第1章 绪论

本书结合IEEE最新发布的软件工程体系SWEBOK&#xff0c;和IEEE/ACM软件工程学科小组公布的软件工程教育知识体系SEEK&#xff0c;北大本科生指定教材。注重基础知识的系统性&#xff0c;选材的先进性及知识的应用。2009年出版 软件开发本质的认识&#xff0c;两大技术问题&…

JUnit5的条件测试、嵌套测试、重复测试

条件测试 JUnit5支持条件注解&#xff0c;根据布尔值判断是否执行测试。 自定义条件 EnabledIf和DisabledIf注解用来设置自定义条件&#xff0c;示例&#xff1a; Test EnabledIf("customCondition") void enabled() { // ... } Test DisabledIf("cust…

Java并发基石ReentrantLock:深入解读其原理与实现

码到三十五 &#xff1a; 个人主页 心中有诗画&#xff0c;指尖舞代码&#xff0c;目光览世界&#xff0c;步履越千山&#xff0c;人间尽值得 ! 在Java的并发编程库中&#xff0c;ReentrantLock是一种非常重要的同步工具&#xff0c;它提供了一种比内置synchronized关键字更加…

科研学习|研究方法——实验法

1.实验方法的渊源 今天我们说物理学、生物学是实验的科学&#xff0c;应该不会有人再持异议了&#xff0c;然而连物理学这样的学科在历史上也并非一开始就是实验科学。在2000多年以前的亚里士多德时代&#xff0c;众人都认为物理学是非实验性质的&#xff0c;物理学成为实验科学…

netty基础_12.用 Netty 自己实现简单的RPC

用 Netty 自己实现简单的RPC RPC 基本介绍我们的RPC 调用流程图己实现 Dubbo RPC&#xff08;基于 Netty&#xff09;需求说明设计说明代码封装的RPCNettyServerNettyServerHandlerNettyClientHandlerNettyClient 接口服务端(provider)HelloServiceImplServerBootstrap 客户端(…

第四百一十四回

文章目录 1. 概念介绍2. 思路与方法2.1 实现思路2.2 实现方法 3. 示例代码4. 内容总结 我们在上一章回中介绍了"自定义标题栏"相关的内容&#xff0c;本章回中将介绍自定义Action菜单.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 概念介绍 我们在这里提到的…

【呼市经开区建设服务项目水、电能耗监测 数采案例】

实施方案 针对能耗采集中的水、电能源数据采集&#xff0c;因客观因素条件&#xff0c;数据采集方面存在较大难度。大多数国网电表485接口由于封签限制&#xff0c;不能实施采集&#xff0c;不让拆机接线&#xff0c;采集实施存在困难。水量能耗采集&#xff0c;存在类似问题&a…

腾讯云GPU服务器深度计算怎么收费?1小时、一个月和一年报价

腾讯云GPU服务器怎么收费&#xff1f;GPU服务器1小时多少钱&#xff1f;一个月收费价格表和一年费用标准&#xff0c;腾讯云百科txybk.com分享腾讯云GPU服务器GPU计算型GN10Xp、GPU服务器GN7、GPU渲染型 GN7vw等GPU实例费用价格&#xff0c;以及NVIDIA Tesla T4 GPU卡和V100详细…

Jmeter Ultimate Thread Group 和 Stepping Thread Group

线程组&#xff1a;使用复杂场景的性能测试 有时候我们做性能测试时&#xff0c;只依靠自带的线程组&#xff0c;显示满足不了性能测试中比较复杂的场景&#xff0c;下面这两种线程组可以帮助你很好的完成复杂的场景 第一种&#xff1a;Stepping Thread Group 在取样器错误后…

Socket类

2.2 Socket类 Socket 类&#xff1a;该类实现客户端套接字&#xff0c;套接字指的是两台设备之间通讯的端点。 构造方法 public Socket(String host, int port) :创建套接字对象并将其连接到指定主机上的指定端口号。如果指定的host是null &#xff0c;则相当于指定地址为回送…

Appium —— 移动应用自动化测试开源工具!

Appium介绍 Appium是一个用于自动化移动应用程序的开源工具&#xff0c;它支持iOS和Android平台。通过Appium&#xff0c;开发人员可以使用各种编程语言&#xff08;如Java、Python、Ruby等&#xff09;编写测试脚本&#xff0c;以自动化测试移动应用程序的功能和用户界面。Ap…

基于springboot+vue的小区团购管理

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…

如何在Windows系统使用VS Code制作游戏网页并实现无公网IP远程访问

文章目录 前言1. 编写MENJA小游戏2. 安装cpolar内网穿透3. 配置MENJA小游戏公网访问地址4. 实现公网访问MENJA小游戏5. 固定MENJA小游戏公网地址 前言 本篇教程&#xff0c;我们将通过VS Code实现远程开发MENJA小游戏&#xff0c;并通过cpolar内网穿透发布到公网&#xff0c;分…

《操作系统实践-基于Linux应用与内核编程》第10章--实验 Qt聊天程序

前言: 内容参考《操作系统实践-基于Linux应用与内核编程》一书的示例代码和教材内容&#xff0c;所做的读书笔记。本文记录再这里按照书中示例做一遍代码编程实践加深对操作系统的理解。 引用: 《操作系统实践-基于Linux应用与内核编程》 作者&#xff1a;房胜、李旭健、黄…

微信小程序调试、断点调试

1、wxml 查看对应的页面组件 2、console面板可以用来打印信息 3、sources 用来断点调试 4、network面板用来调试接口 5、storage面板 可以查看每个key对应的value内容&#xff0c;这些数据在用户使用小程序时被持久化保存在本地。

【mac M3】idea删除不用或者失效的jdk

【mac M3】idea删除不用或者失效的jdk 不用&#xff08;重复&#xff09;或者失效的jdk如下&#xff1a; 重复或者已失效的JDK版本出现在下拉列表中不仅影响美观&#xff0c;也影响效率&#xff0c;删除jdk的步骤如下&#xff1a; 步骤1.点击File 步骤2.选择Project Structure…

【C语言】文件操作揭秘:C语言中文件的顺序读写、随机读写、判断文件结束和文件缓冲区详细解析【图文详解】

欢迎来CILMY23的博客喔&#xff0c;本篇为【C语言】文件操作揭秘&#xff1a;C语言中文件的顺序读写、随机读写、判断文件结束和文件缓冲区详细解析【图文详解】&#xff0c;感谢观看&#xff0c;支持的可以给个一键三连&#xff0c;点赞关注收藏。 前言 欢迎来到本篇博客&…

Java AOP 简单实例演示

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…