45. UE5 RPG 使用元属性(Meta Attributes)以及使用Set by Caller修改伤害

news2024/10/7 10:13:59

在RPG游戏中,我们是不会直接修改生命值的属性,是因为在修改角色属性时,需要获取角色的属性并进行复杂的计算,所以,我们正常情况下使用元属性(Meta Attributes)作为计算的中间的媒。在服务器上先将属性计算到元属性上面,然后再通过元属性的数值去修改实际属性。
那元属性和普通的属性有什么区别?
普通的Gameplay Attribute:它是经常被复制的,在服务器上面修改,然后复制到每个客户端上面。
元属性:它不会被复制,只做为一个临时缓冲占位符,只在服务器上面计算,然后使用元属性修改实际需求修改的属性,这样就可以避免每个端需要复杂的计算。
比如,我们将实现一个名为IncomingDamage的元属性,然后在属性集里的PostGameplayEffectExecute获取角色属性(是否被格挡,减伤等等)来计算出对角色造成的最终伤害,然后将最终伤害去修改角色的血量值,而这个值再复制给客户端,将大大减少计算量。
所以,这些计算伤害的元属性将有传入的GE去计算,然后属性集去执行所需的计算,并播放对应的效果(比如显示不同颜色的伤害数字)并对目标应用buff(如果有)。

接下来,我们将从一个简单的版本开始实现,然后逐渐让功能符合游戏需求。

创建元属性

在这里插入图片描述
在测试使用了GE里面,我们是直接修改了血量值,我们需要创建一个元属性作为中间媒介。
首先,我们需要先在属性集(AttributeAet)里添加一个属性,用于作为临时占位符使用。原属性不需要赋值,所以不需要赋值函数,但是属性对应的宏还是需要的生成获取和设置的函数使用。

	UPROPERTY(BlueprintReadOnly, Category="Meta Attributes")
	FGameplayAttributeData IncomingDamage; //处理传入的伤害
	ATTRIBUTE_ACCESSORS(UAttributeSetBase, IncomingDamage);

接下来,在PostGameplayEffectExecute函数里面,查看修改的是否为元属性

if(Data.EvaluatedData.Attribute == GetIncomingDamageAttribute())

然后我们获取到元属性的值备用,并将属性集上的值设置为0,等待下一次设置。

const float LocalIncomingDamage = GetIncomingDamage();
SetIncomingDamage(0.f);

接下来,判断值是否大于0,如果大于0则传入了伤害

if(LocalIncomingDamage > 0.f)

然后,我们先实现最基础的修改血量,作为基础模板,并且还判断角色是否存活,条件就是血量不为0则为存活,这样基础测试代码就实现了。

	if(Data.EvaluatedData.Attribute == GetIncomingDamageAttribute())
	{
		const float LocalIncomingDamage = GetIncomingDamage();
		SetIncomingDamage(0.f);
		if(LocalIncomingDamage > 0.f)
		{
			const float NewHealth = GetHealth() - LocalIncomingDamage;
			SetHealth(FMath::Clamp(NewHealth, 0.f, GetMaxHealth()));

			const bool bFatal = NewHealth <= 0.f; //血量小于等于0时,角色将会死亡
		}
	}

编译代码,打开UE,在GE里面修改的为IncomingDamage,并设置为25
在这里插入图片描述
就可以运行测试效果
在这里插入图片描述

使用Set by Caller来实现伤害数值的传递

制作到这里,朋友们会有疑问,我们实现GE里面的伤害都是通过固定的数值来造成的伤害,但是如果我们需要通过角色的属性计算呢,该如何实现?
这就需要将属性值修改的Set by Caller去实现
在这里插入图片描述
接下来我们将一步步实现这个。
要使用这种方式去设置,我们需要使用一个标签作为Key,在我们之前c++里添加一个标签

FGameplayTag Damage; //伤害 标签

然后初始化,添加到标签管理器,并缓存下来变量

	GameplayTags.Damage = UGameplayTagsManager::Get()
	.AddNativeGameplayTag(
		FName("Damage"),
		FString("伤害标签")
		);

创建完成这个,我们需要在之前的火球术技能类里面,在生成GESpec时,使用标签设置。
首先获取到标签的单例

const FMyGameplayTags GameplayTags = FMyGameplayTags::Get(); //获取标签单例

然后使用函数库的方法设置,这里有两种方式,一种是FName,另一种是使用标签,对应在GE上获取的两种,由于Name类型容易写错,所以个人推荐使用标签。最后的值则是我们需要对目标造成的伤害,这里方便测试,我们直接写了固定数值,如果这个数值能够起作用,证明我们接下来可以在代码里面计算当前技能造成的伤害。

//UAbilitySystemBlueprintLibrary::AssignSetByCallerMagnitude() //使用DataName设置
UAbilitySystemBlueprintLibrary::AssignTagSetByCallerMagnitude(SpecHandle, GameplayTags.Damage, 50.f);

然后编译代码,打开GE,将修改数值类型设置为Set by Caller,并在下面设置Tag为Damage,这样,GE将从标签获取对应的数值
在这里插入图片描述

在技能上通过技能等级设置伤害

我们实现了通过代码里面去设置技能造成的伤害,接下来,我们将实现增加配置项在技能上实现对伤害的设置,并且还使用到了曲线表格去编辑伤害。
首先我们在技能基类上面添加一个属性,虽然不是所有的属性都会用到,但是它占用的内存不大,所以我们直接写到基类,需要就用。

	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Damage")
	FScalableFloat Damage;

编译代码打开UE,可以查看到属性面板
在这里插入图片描述
所以,我们需要设置它的曲线表格来实现通过等级设置技能伤害,首先创建一个JSON文件,用来设置属性
在这里插入图片描述
然后导入到UE,生成曲线表格
在这里插入图片描述
设置为曲线表格
在这里插入图片描述
然后可以稍微修改一下表格,让曲线更陡一些
在这里插入图片描述
然后将属性缩放设置为1,选择我们创建的表格,然后设置好使用哪一行
在这里插入图片描述
有了表格以后,我们就需要实现如何通过属性获取到数值。如果你需要获取到整数类型的,我们可以通过Damage.AsInteger(GetAbilityLevel())来获取从表格转换的整数数值。
这里我们使用Damage.GetValueAtLevel获取浮点数来设置,并且将数值打印到窗口

//创建一个GE的实例,并设置给投射物
const UAbilitySystemComponent* SourceASC = UAbilitySystemBlueprintLibrary::GetAbilitySystemComponent(GetAvatarActorFromActorInfo());
const FGameplayEffectSpecHandle SpecHandle = SourceASC->MakeOutgoingSpec(DamageEffectClass, GetAbilityLevel(), SourceASC->MakeEffectContext());

const FMyGameplayTags GameplayTags = FMyGameplayTags::Get(); //获取标签单例
const float ScaledDamage = Damage.GetValueAtLevel(GetAbilityLevel()); //根据等级获取技能伤害
GEngine->AddOnScreenDebugMessage(-1, 3.f, FColor::Red, FString::Printf(TEXT("火球术伤害:%f"), ScaledDamage));
//UAbilitySystemBlueprintLibrary::AssignSetByCallerMagnitude() //使用DataName设置
UAbilitySystemBlueprintLibrary::AssignTagSetByCallerMagnitude(SpecHandle, GameplayTags.Damage, ScaledDamage);

Projectile->DamageEffectHandle = SpecHandle;

编译并运行项目测试
在技能等级没有修改时,值为5,没问题
在这里插入图片描述
由于我们现在还没有实现设置技能等级,所以这里在代码里修改查看20级的数值,是否为我们设置的伤害值

const float ScaledDamage = Damage.GetValueAtLevel(GetAbilityLevel() + 19);

查看效果,没问题
在这里插入图片描述

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

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

相关文章

中间件之异步通讯组件RabbitMQ进阶

这里我们必须尽可能确保MQ消息的可靠性&#xff0c;即&#xff1a;消息应该至少被消费者处理1次 那么问题来了&#xff1a; 我们该如何确保MQ消息的可靠性&#xff1f; 如果真的发送失败&#xff0c;有没有其它的兜底方案&#xff1f; 首先&#xff0c;我们一起分析一下消息…

django设计模式理解FBV和CBV

在 Web 开发中&#xff0c;FBV&#xff08;Function-Based Views&#xff09;和 CBV&#xff08;Class-Based Views&#xff09;是两种常见的视图设计模式&#xff0c;用于处理 HTTP 请求并生成相应的响应。下面是它们的简要解释&#xff1a; Function-Based Views (FBV) 在 …

Mac环境下ollama部署和体验

欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码)&#xff1a;https://github.com/zq2599/blog_demos 关于ollama ollama和LLM&#xff08;大型语言模型&#xff09;的关系&#xff0c;类似于docker和镜像&#xff0c;可以在ollama服务中管理和运行各种LLM&…

基于java,SpringBoot和VUE的求职招聘简历管理系统设计

摘要 基于Java, Spring Boot和Vue的求职招聘管理系统是一个为了简化求职者与雇主间互动流程而设计的现代化在线平台。该系统后端采用Spring Boot框架&#xff0c;以便快速搭建具有自动配置、安全性和事务管理等特性的RESTful API服务&#xff0c;而前端则使用Vue.js框架构建动…

UE5入门学习笔记(六)——编译低版本插件

对于有些低版本的插件&#xff0c;可以通过此方法自己编译到高版本而无需等待插件作者更新 使用工具&#xff1a;如图所示 步骤1&#xff1a;打开cmd&#xff0c;并使用cd命令切换到此目录 步骤2&#xff1a;输入如下指令 RunUAT.bat BuildPlugin -Plugin“路径1” -Package“…

Vitis HLS 学习笔记--MAXI手动控制突发传输

目录 1. 简介 2. MAXI 突发传输详解 2.1 突发传输的前置条件 2.2 hls::burst_maxi 详解 2.2.1 基本知识 2.2.2 hls::burst_maxi 构造函数 2.2.3 hls::burst_maxi 读取方法 2.2.4 hls::burst_maxi 写入方法 2.3 示例一 2.4 示例二 3. 总结 1. 简介 这篇文章探讨了在…

Java 新手上路常见的5个经典问题,你遇到过吗?

当我们开始学习一门新的编程语言或者开发平台时&#xff0c;经常会遇到一些常见的问题。这些问题不仅是学习过程中的一部分&#xff0c;也是成长和提高的机会。 1. 空指针异常&#xff08;NullPointerException&#xff09; 空指针异常是 Java 开发中最常见的问题之一。它的产…

【AI大模型应用开发】3. RAG初探 - 动手实现一个最简单的RAG应用

0. 什么是RAG 大模型也不是万能的&#xff0c;也有局限性。 LLM 的知识不是实时的LLM 可能不知道你私有的领域/业务知识 RAG&#xff08;Retrieval Augmented Generation&#xff09;顾名思义&#xff1a;通过检索的方法来增强生成模型的能力。你可以把这个过程想象成开卷考…

TCP协议在物联网中的实战

一、TCP协议介绍 网上对TCP协议介绍众多&#xff0c;本人按照自己的理解简单介绍一下。 TCP&#xff08;Transmission Control Protocol&#xff0c; 传输控制协议&#xff09;是一种面向连接的、可靠的、基于字节流的传输控制层通信协议。 1.1 协议机制 1.1.1 三次握手 &…

基于Springboot的民宿管理平台

基于SpringbootVue的民宿管理平台设计与实现 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringbootMybatis工具&#xff1a;IDEA、Maven、Navicat 系统展示 用户登录 首页 民宿信息 后台登录 后台首页 用户管理 商家管理 民宿信息管理 房间类型管理 …

C. Assembly via Remainders

C.通过余数组装 每次测试时限&#xff1a;2 秒 每次测试的内存限制&#xff1a;256 兆字节 输入&#xff1a;标准输入 输出&#xff1a;标准输出 思路分析 我们用arr数组存放输入的数据,用brr代表代表答案数组,我们可以看到答案的第一位是都是arr的首位1,然后我们观察可…

【研发管理】产品经理知识体系-组合管理

导读&#xff1a;新产品开发的组合管理是一个重要的过程&#xff0c;它涉及到对一系列新产品开发项目进行策略性选择、优先级排序、资源分配和监控。这个过程旨在确保企业能够最大化地利用有限的资源&#xff0c;以实现其战略目标。 目录 1、组合管理、五大目标 2、组合管理的…

Numerical Analysis(byRichard.L..Burden)【pdf高清英文原版】

专栏导读 作者简介&#xff1a;工学博士&#xff0c;高级工程师&#xff0c;专注于工业软件算法研究本文已收录于专栏&#xff1a;《有限元编程从入门到精通》本专栏旨在提供 1.以案例的形式讲解各类有限元问题的程序实现&#xff0c;并提供所有案例完整源码&#xff1b;2.单元…

Linux下top命令指标说明

目录 Linux下top命令指标说明1. 概览2. CPU利用率3. 内存利用率4. 进程信息 Linux下top命令指标说明 在Linux系统中&#xff0c;top 命令是一个用于实时监视系统运行状态的工具。通过 top 命令&#xff0c;我们可以了解系统的负载情况、CPU利用率、内存使用情况以及各个进程的…

k8s环境部署gpu以及CUDA兼容性分析

本文记录和学习在实用gpu搭建k8s支持上层应用时的功能实践和遇到的问题。 1. 基础概念 CUDA本质上就是NVIDIA专为通用高性能并行计算设计的一套计算平台和编程模型&#xff0c;换句话使用GPU并行编程的规范方法&#xff0c;所以CUDA在软件层面包含了众多库&#xff0c; 那这里…

《QT实用小工具·五十一》带动画的 CheckBox

1、概述 源码放在文章末尾 该项目实现了带动画效果的多选框&#xff0c;鼠标放在上面或者选中都会呈现炫酷的动画效果&#xff0c;demo演示如下&#xff1a; 项目部分代码如下所示&#xff1a; #ifndef LINEARCHECKBOX_H #define LINEARCHECKBOX_H#include <QCheckBox> …

图像处理1,灰度,data,for循环批处理图片,图片属性查看,图片单通道查看,椒盐噪声的生成,滤波处理,图像分割

图像处理1 灰度处理data库的使用for循环批处理图像对图像属性的查看图片类型图片尺寸图片宽度图像高度通道数总像素个数最大像素值最小像素值&#xff0c;像素平均值图像点像素值 for循环分别显示图像rgb通道椒盐噪声的生成中值滤波处理高斯模糊处理图像切割 灰度处理 from sk…

多国语言免费在线客服系统源码,网站在线客服系统,网页在线客服软件在线聊天通讯平台

详情介绍 多国语言免费在线客服系统源码,网站在线客服系统,网页在线客服软件在线聊天通讯平台 新款在线客服系统全开源无加密:多商户、国际化多语言、智能机器人、自动回复、语音聊天、 文件发送、系统强力防黑加固、不限坐席、国际外贸、超多功能 支持手机移动端和PC网页…

如何从Mac电脑恢复任何删除的视频

Microsoft Office是包括Mac用户在内的人们在世界各地创建文档时使用的最佳软件之一。该软件允许您创建任何类型的文件&#xff0c;如演示文稿、帐户文件和书面文件。您可以使用 MS Office 来完成。所有Microsoft文档都可以在Mac上使用。大多数情况下&#xff0c;您处理文档&…

私有开源LLM实例的三个考虑因素

原文地址&#xff1a;three-considerations-for-private-open-source-llm-instances 2024 年 4 月 29 日 在生产应用中使用商业 LLM APIs 会带来明确且经过充分研究的风险。因此&#xff0c;企业越来越多地转向利用开源的私有托管LLM实例&#xff0c;并通过RAG技术进行增强。 介…