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

在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.mzph.cn/diannao/6030.shtml

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

相关文章

【讲解下如何解决一些常见的 Composer 错误】

&#x1f308;个人主页: 程序员不想敲代码啊 &#x1f3c6;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f44d;点赞⭐评论⭐收藏 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共…

Apache Dubbo知识点表格总结

Dubbo是一个高性能的Java RPC框架&#xff0c;它提供了一系列的功能来支持分布式系统的开发。通常用于微服务之间的服务调用&#xff0c;顺便提一下也是用于微服务之间调用的OpenFeign&#xff0c;OpenFeign是Spring Cloud体系中的一个声明式HTTP客户端&#xff0c;用于简化HTT…

Django知识点总结

因为最近在搞一个Python项目&#xff0c;使用的Django框架。所以快速学习了一下这个web框架。并做一些总结。 Django官网的介绍&#xff1a;Django is a high-level Python web framework that encourages rapid development and clean, pragmatic design. Built by experience…

Ex1-C6油气化工防爆轮式巡检机器人

Ex1系列防爆轮式巡检机器人整机采用防爆设计&#xff0c;防爆等级为Exd II CT4 Gb。机器人通过无轨3D形态导航技术&#xff0c;结合360度防爆云台和无线防爆充电桩&#xff0c;实现整套防爆标准&#xff0c;可广泛应用于石油、燃气、化工、冶金等II类爆炸环境中&#xff0c;代替…

设计模式:建造者模式

目录 一&#xff0c;概念 二&#xff0c;不使用建造者有什么麻烦 三&#xff0c;格式 一&#xff0c;概念 建造者模式&#xff08;Builder Pattern&#xff09;是一种创建型设计模式&#xff0c;用于将复杂对象的构建与其表示分离&#xff0c;以便同样的构建过程可以创建不同…

大模型公开可用的模型检查点或 API

文章目录 公开可用的模型检查点或 APILLaMA 变体系列大语言模型的公共 API 公开可用的模型检查点或 API 众所周知&#xff0c;大模型预训练是一项对计算资源要求极高的任务。因此&#xff0c;经过预训练的公开模型检查点&#xff08;Model Checkpoint&#xff09;对于推动大语言…

nginx封禁恶意IP

网络攻击时有发生 TCP洪水攻击、注入攻击、DOS等比较难防的有DDOS等 为了数据安全&#xff0c;防止对手爬虫恶意爬取&#xff0c;封禁IP 一般封禁ip linux server层面封IP&#xff1a;iptablesnginx层面封IP&#xff0c;方式多种&#xff08;但req还是会打进来&#xff0c;让…

21-ESP32-S3实时时钟(RTC)

ESP32-S3实时时钟&#xff08;RTC&#xff09;的使用 ESP32-S3是一款高性能的Wi-Fi和蓝牙集成的系统级芯片&#xff08;SoC&#xff09;&#xff0c;它包含一个实时时钟&#xff08;RTC&#xff09;模块&#xff0c;可以在系统的其他部分关闭时继续运行&#xff0c;以节省电能…

IDEA 申请学生许可证

如果你有学生账号&#xff0c;并且账号是 EDU 结尾的&#xff0c;可以申请 IDEA 的学生许可证。 有效期一年&#xff0c;完全免费。 在界面上输入邮件地址&#xff0c;然后单击按钮提交。 邮件中单击链接 JetBrains 会把一个带有链接的邮件发送到你的邮箱中。 单击邮箱中的…

Flask知识点汇总表格总结

最近接手的Python项目有两个&#xff0c;一个是Django项目&#xff0c;一个是Flask项目&#xff0c;Django昨天做了一个比较全面的总结&#xff0c;今天再就Flask做一个知识总结。我这相当于是项目驱动学习类型。 Flask是一个轻量级的Python Web应用框架&#xff0c;它被设计为…

智能数据分析平台待修复BUG以及待完成需求

快速跳转&#xff1a;何耳林毕设项目介绍-CSDN博客 BUG 1.个人图标页搜索功能&#xff0c;不能进行搜索 2.用户管理功能头部搜索栏有多余搜索项 3.修改用户权限等信息会影响当前管理用户 待完成需求 1.新增AI问答功能 2.图标页自动刷新功能 3.将个人页更改到头像下拉框&…

分类规则挖掘(三)

目录 四、贝叶斯分类方法&#xff08;一&#xff09;贝叶斯定理&#xff08;二&#xff09;朴素贝叶斯分类器&#xff08;三&#xff09;朴素贝叶斯分类方法的改进 五、其它分类方法 四、贝叶斯分类方法 贝叶斯 (Bayes) 分类方法是以贝叶斯定理为基础的一系列分类算法的总称。贝…

【C++STL详解(五)】--------list的介绍与使用

目录 前言 一、list的介绍 二、list的使用 Ⅰ.默认成员函数 1、构造函数 2、赋值重载 3、析构函数 Ⅱ、容量 1.size() Ⅲ、迭代器与遍历 1.beginend (正向迭代器) 2.rbeginrend (反向迭代器) 3.front 4.back Ⅳ、增删查改 1.push_front 2.pop_front 3.push_b…

目标跟踪难点及算法介绍

目标跟踪是计算机视觉领域的一个重要问题&#xff0c;目前广泛应用在体育赛事转播、安防监控和无人机、无人车、机器人等领域。 简单来说&#xff0c;目标跟踪就是在连续的视频序列中&#xff0c;建立所要跟踪物体的位置关系&#xff0c;得到物体完整的运动轨迹。给定图像第一帧…

c3 笔记7 css基本语法

相关内容&#xff1a;字体、段落、词间距、文字效果&#xff08;对齐、上下标、阴影&#xff09;、背景图、背景渐变、…… 单位pt与px的差别pt是印刷使用的字号单位&#xff0c;不管屏幕分辨率是多少&#xff0c;打印到纸上看起来都是相同的&#xff0c;lot的长度是0.01384英寸…

【STM32+HAL】SDIO+DMA模式读写SD卡

一、准备工作 有关CUBEMX的初始化配置&#xff0c;参见我的另一篇blog&#xff1a;【STM32HAL】CUBEMX初始化配置 二、所用工具 1、芯片&#xff1a; STM32F407ZGT6 2、IDE&#xff1a; MDK-Keil软件 3、库文件&#xff1a;STM32F4xxHAL库 三、实现功能 实现用SDIODMA读写S…

Python网络编程:从基础到实践

Python 是一种广泛应用于网络编程的高级编程语言&#xff0c;它简单易学&#xff0c;功能强大&#xff0c;深受广大开发者的喜爱。本文将带你深入了解 Python 网络编程的基础知识&#xff0c;并通过实际案例&#xff0c;让你掌握如何使用 Python 进行网络编程。 第一部分&…

05_机器学习赛事_优惠券使用预测

1. 函数库导入 # import libraries necessary for this project import os, sys, pickleimport numpy as np import pandas as pdimport matplotlib.pyplot as plt import matplotlib.dates as mdatesimport seaborn as sns import datetime as dtfrom datetime import datefr…

如何删除BigKey

③第三方工具 利用第三方工具&#xff0c;如 Redis-Rdb-Tools 分析RDB快照文件&#xff0c;全面分析内存使用情况https://github.com/sripathikrishnan/redis-rdb-tools ④网络监控 自定义工具&#xff0c;监控进出Redis的网络数据&#xff0c;超出预警值时主动告警一般阿里…

MVCC如何根据read view结合行数据的undo log版本链过滤数据的?

先明确定义 行数据的最新undo log事务id 按顺序判断 比最小的小&#xff0c;一定读:行数据的最新undo log事务id比min_trx_id还小&#xff0c;说明这个产生这条undo log的事务在read view产生时刻已经被提交了。 如果行数据的最新undo log事务id和当前事务id相等&#xff0…