43. UE5 RPG 实现敌人血量显示条

在上一篇文章中,我们实现了火球术伤害功能,在火球击中敌方目标,可以降低敌人20的血量,这个值现在是固定的,后面我们会修改火球的伤害设置。接着,我们也测试了功能是实现的,但是在正常的游玩过程中,你不可能让玩家通过log界面获取敌人血量,这不符合玩家体验,所以,这一篇我们来实现在敌人的上方显示敌人剩余血量的UI。
为了实现敌人的血量条,我们首先将创建一个显示血量的用户控件,然后再敌人的基类里面实现在敌人血量变化时,对敌人的血量进行事件委托广播,来告知敌人修改血量。有个重点就是,我们自己定义的用户控件需要一个用户控件控制器作为中间媒介来获取数据,这里我们直接将敌人类作为控制器使用,没必要额外创建控制器。

在角色身上增加显示血条的UI组件

首先,我们要在敌人基类身上添加一个属性,用于配置使用的显示血条的用户控件

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Widget")
	TObjectPtr<UWidgetComponent> HealthBar;

接着在构造函数中,创建实例,并将其附加到根节点

	HealthBar = CreateDefaultSubobject<UWidgetComponent>("HealthBar");
	HealthBar->SetupAttachment(GetRootComponent()); //将血条附件到根节点上

接着编译打开UE,打开敌人的基类,我们通用的都会在基类身上设置,这样也会同步到子类身上,角色基类会出现我们创建的用户控件
在这里插入图片描述
在右侧的属性上,我们使用屏幕空间,然后以所需大小绘制,我们UI设置尺寸多大,它就按多大渲染。注意:每帧修改尺寸大小消耗极大,所以,我们使用它不要去修改大小,而是在内部去修改。
在这里插入图片描述
显示用的组件有了,我们还需要添加的用户控件,接下来,我们创建血条的UI控件。

创建基础血条

我们要创建一个敌人专门使用的进度条,这个进度条作为进度条的基础控件,里面可以设置一些通用的方法,用于以后扩展子类。
在这里插入图片描述
我们先在下方创建一个尺寸框,用于调节它的尺寸大小
在这里插入图片描述
将显示设置为所需,我们设置尺寸框多大,它就显示多大。然后将尺寸框设置为变量,并开启宽高和高度重载。
在这里插入图片描述
接着,我们实现使用变量控制它的宽高,使用节点重新控制它的宽高。编译以后,可以修改变量在构造时设置大小,选中节点右键折叠到函数,可以直接编译成一个函数。
在这里插入图片描述
接着,我们创建一个覆层,可以让下面的UI相互叠加,方便后面实现一个血条渐变的效果。
在这里插入图片描述
然后在覆层下面添加一个进度条
在这里插入图片描述
我们将进度条的背景填充的透明度设置为0,不使用它的背景色。
在这里插入图片描述
在外观这里修改将颜色修改为白色,我们将使用颜色去修改进度条颜色
在这里插入图片描述

将其设置为变量
在这里插入图片描述
我们在蓝图节点中设置它的样式,先将背景设置为透明,然后使用笔刷设置它的填充颜色
在这里插入图片描述
我们可以通过调整百分比查看它的进度,这个值我们将会在实现委托后,通过蓝图节点设置它。
在这里插入图片描述

创建委托

我们之前提到过,要将角色作为血条的控制器层使用,所以,我们接下来要在敌人基类身上增加委托实现对敌人血量和最大血量的广播。
回想一下,我们之前在设置主角属性面板时,我们创建了血量委托和蓝量委托,我们接着使用同样的方式实现。
在这里插入图片描述
我们在敌人基类里面增加血量的委托函数

	UPROPERTY(BlueprintAssignable)
	FOnAttributeChangedSignature OnHealthChanged;

	UPROPERTY(BlueprintAssignable)
	FOnAttributeChangedSignature OnMaxHealthChanged;

这里我们直接使用OverlayWidgetController里面的委托宏,所以,需要将OverlayWidgetController的文件引入

#include "UI/WidgetController/OverlayWidgetController.h"

接下来,我们就要实现对委托的广播,让它在合适的地方去广播,首先就是创建完成后,进行一次委托,用于初始化显示,接着就是绑定血量数值的变化,在数值变化时,及时更新数值。
首先,我们要将敌人的基类作为控制器设置给用户控件,可以在用户控件绑定对应监听,我们在初始化完成后,开始执行事件时,从用户控件组件中获取到用户控件,转换为我们创建的用户控件基类的实力,调用方法设置。这个方法会在设置后,触发设置回调

void AEnemyBase::BeginPlay()
{
	Super::BeginPlay();

	//初始化角色的ASC
	InitAbilityActorInfo();

	if(UMyUserWidget* UserWidget = Cast<UMyUserWidget>(HealthBar->GetUserWidgetObject()))
	{
		UserWidget->SetWidgetController(this);
	}

我们将AttributeSet(AS)转换成我们自己创建的类型,这样我们可以获取到它的血量属性

	UAttributeSetBase* AS = Cast<UAttributeSetBase>(AttributeSet);
	if(AS)
	{...

然后,我们通过ASC监听AS内的血量数值变化,绑定血量变化回调,在血量变动时,将会触发回调。由于进入游戏没有初始化,所以,我们需要进行初始化,设置它的初始值,在出生后,数值显示正确。

	if(UAttributeSetBase* AS = Cast<UAttributeSetBase>(AttributeSet))
	{
		//监听血量变化
		AbilitySystemComponent->GetGameplayAttributeValueChangeDelegate(AS->GetHealthAttribute()).AddLambda(
			[this](const FOnAttributeChangeData& Data)
			{
				OnHealthChanged.Broadcast(Data.NewValue);
			}
		);
		AbilitySystemComponent->GetGameplayAttributeValueChangeDelegate(AS->GetMaxHealthAttribute()).AddLambda(
			[this](const FOnAttributeChangeData& Data)
			{
				OnMaxHealthChanged.Broadcast(Data.NewValue);
			}
		);

		//初始化血量
		OnHealthChanged.Broadcast(AS->GetHealth());
		OnMaxHealthChanged.Broadcast(AS->GetMaxHealth());
	}

完整函数

void AEnemyBase::BeginPlay()
{
	Super::BeginPlay();

	//初始化角色的ASC
	InitAbilityActorInfo();

	if(UMyUserWidget* UserWidget = Cast<UMyUserWidget>(HealthBar->GetUserWidgetObject()))
	{
		UserWidget->SetWidgetController(this);
	}
	
	if(const UAttributeSetBase* AS = Cast<UAttributeSetBase>(AttributeSet))
	{
		//监听血量变化
		AbilitySystemComponent->GetGameplayAttributeValueChangeDelegate(AS->GetHealthAttribute()).AddLambda(
			[this](const FOnAttributeChangeData& Data)
			{
				OnHealthChanged.Broadcast(Data.NewValue);
			}
		);
		AbilitySystemComponent->GetGameplayAttributeValueChangeDelegate(AS->GetMaxHealthAttribute()).AddLambda(
			[this](const FOnAttributeChangeData& Data)
			{
				OnMaxHealthChanged.Broadcast(Data.NewValue);
			}
		);

		//初始化血量
		OnHealthChanged.Broadcast(AS->GetHealth());
		OnMaxHealthChanged.Broadcast(AS->GetMaxHealth());
	}
}

创建敌人专用血条

我们上面创建了一个基础显示血条的用户控件,并且在敌人基类上实现了血量委托,接下来,我们将实现专门用于到敌人身上的血条。
我们创建一个新的控件蓝图,父类选择之前创建的基本的进度条。
在这里插入图片描述
有了敌人对应的控件后,我们首先去敌人蓝图基类去设置上
在这里插入图片描述
在用户控件事件里面,首先设置回调,将类型转换成敌人基类,这样,我们就可以使用控制器绑定回调了。
在这里插入图片描述
然后设置监听血量和最大血量广播,接着设置给进度条来实现血量减少变化。并且除以的时候我们使用Safe Divide节点,这个可以保证在除以0的时候不会报错。
在这里插入图片描述
为了通用,我们在它的父类创建一个设置百分比的,我们先将上层的设置百分比的实现,避免在子类里面每次都要去创建
在这里插入图片描述
在子类改成调用函数即可
在这里插入图片描述
接着可以运行测试了,我们发现功能实现了,血条的位置有点太靠中间了。
在这里插入图片描述
打开敌人基类蓝图,修改血条位置
在这里插入图片描述
现在显示正常。
在这里插入图片描述

添加逐渐消失的进度条

基础功能我们实现了,后面我们增加一些体验的功能,一个是受到攻击后,扣除血量,我们将显示一个逐渐过渡的条,能够让玩家清楚这一次攻击造成了多少伤害。
首先在进度条基类上面,增加额外的进度条这个进度条,这个进度条需要放在血条的上面,这样在覆层里面血条会优先显示。
在这里插入图片描述
接着将它修改名称,并设置为变量,修改对齐
在这里插入图片描述
记得将它的填充设置为白色。
在这里插入图片描述
使用蓝图节点修改它的颜色
在这里插入图片描述
然后修改完它的默认值以后,看一下最终效果
在这里插入图片描述
接下来,我们将实现逐渐消失进度条的效果,我们需要一个值,用于代表当前它所在的位置
在这里插入图片描述
它的默认值为1,就是默认满血
在这里插入图片描述
那么如何实现它平滑的过渡呢,我们使用Finterp To节点,这个节点需要我们传入一个当前值,和一个目标值,然后把时间传入,最后设置一下速度。我们只需要修改它的目标值,就可以实现缓慢的渐变效果。
在这里插入图片描述
将它折叠成函数,就实现了效果
在这里插入图片描述
如果创建的子类,在子类里面如果没有调用父类的帧回调,那它将不会执行,那么如何在子类里面去调用父类的帧回调呢,默认是不会调用的,右键找到节点的将调用添加到父函数,这样就可以生成一个调用父节点的帧回调事件的节点
在这里插入图片描述
在这里插入图片描述
现在我们还需要一个设置最终值的事件,我们创建一个自定义事件,在扣血以后,让它先显示一秒后,在逐渐消失
在这里插入图片描述
这个事件的调用,我们直接在修改了血量百分比这里设置即可。
在这里插入图片描述
接着运行测试,看看功能是否完成
在这里插入图片描述

设置血量条的显隐

接下来又是一个优化的效果,在游戏战斗中,我们不希望敌人的血量条一直显示,而是在被攻击后,将显示一段时间,这样不但可以节省性能,还能够让玩家清楚的知道攻击了哪些敌人。
敌人的血条默认将不会显示,在受到攻击后显示一段时间。
首先,我们增加一个函数,用于显示或隐藏,通过传入一个变量用于设置,并将此变量值记录下来,用于后面使用
在这里插入图片描述
首先,我们实现敌人创建后隐藏血条,那我们在构造完成,开始执行事件时,调用此函数隐藏
在这里插入图片描述
接下来是受伤显示,敌人受伤后,会触发血量回调,那我们可以在修改血量百分比的函数内调用显示
在这里插入图片描述
接下来是隐藏功能,我们需要一个定时器,在一定时间后,设置血条的隐藏,定时器也是无法在函数内使用的,那我们在设置血条渐变效果后面执行,在执行一个新的定时器时,一定要将旧的先清除,我们默认它显示6秒,如果6秒内定时器没有被清除,将触发事件,隐藏血条。
在这里插入图片描述
接下来就是变量的使用,我们设置显示隐藏时,设置了一个变量,这个变量可以用于,设置帧回调事件,可以节约性能,因为帧回调每帧都执行。
我们设置只有在显示时,才会执行帧回调。
在这里插入图片描述
接下来就是测试功能
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

PotatoPie 4.0 实验教程(22) —— FPGA实现摄像头图像对数(log)变换

什么是图像的log变换&#xff1f; 总的来说&#xff0c;对数变换是一种常用的图像增强技术&#xff0c;可以改善图像的视觉质量、减少噪声以及突出图像中的细节&#xff0c;从而提高图像在视觉感知和分析中的效果和可用性。 图像的对数变换&#xff08;log transformation&am…

Canal入门使用

说明&#xff1a;canal [kə’nl]&#xff0c;译意为水道/管道/沟渠&#xff0c;主要用途是基于 MySQL 数据库增量日志解析&#xff0c;提供增量数据订阅和消费&#xff08;官方介绍&#xff09;。一言以蔽之&#xff0c;Canal是一款实现数据同步的组件。可以实现数据库之间、数…

【氮化镓】p-GaN HEMTs空穴陷阱低温冻结效应

这篇文章是关于低温条件下p-GaN高电子迁移率晶体管&#xff08;HEMTs&#xff09;栅极漏电的研究。文章通过电容深能级瞬态谱&#xff08;C-DLTS&#xff09;测试和理论模型分析&#xff0c;探讨了空穴陷阱对栅极漏电电流的影响。以下是对文章的总结&#xff1a; 摘要&#xf…

前端JS加密库CryptoJS的常用方法

CryptoJS是前端常用的一个加密库&#xff0c;如MD5、SHA256、AES等加密算法。 官方文档&#xff1a;https://www.npmjs.com/package/crypto-js 安装方法 方法一&#xff1a;直接在html文件中引入 <script type"text/javascript" src"path-to/bower_componen…

(六)几何平均数计算 补充案例 #统计学 #CDA学习打卡

一. 两个案例 1&#xff09;几何平均数计算&#xff1a;基金年平均增长率计算 在财务、投资和银行业的问题中&#xff0c;几何平均数的应用尤为常见&#xff0c;当你任何时候想确定过去几个连续时期的平均变化率时&#xff0c;都能应用几何平均数。其他通常的应用包括物种总体…

[Linux][网络][网络编程套接字][一][预备知识][套接字地址结构]详细讲解

目录 0.预备知识1.理解源IP地址和目的IP地址2.理解源MAC地址和目的MAC地址3.端口号4.理解端口号和进程ID5.理解源端口号和目的端口号6.通过IP地址、端口号、协议号进行通信识别7.认识TCP协议和UDP协议8.网络字节序 1.套接字地址结构(sockaddr) 0.预备知识 1.理解源IP地址和目的…

安装配置Maven(idea里面配置)

放在这个路径下&#xff08;如果需要可以免费发给你&#xff0c;dd我就好了&#xff09; D:\IearnSoftware\maven\apache-maven-3.6.1-bin.zip&#xff08;我自己的路径下面&#xff0c;防止忘记&#xff09; 1.首先测试maven在不在&#xff0c;配置对不对 mvn -v 这样就是成…

SpringMVC进阶(数据格式化以及数据校验)

文章目录 1.数据格式化1.基本介绍1.基本说明2.环境搭建 2.基本数据类型和字符串转换1.需求分析2.环境搭建1.data_valid.jsp首页面2.Monster.java封装请求信息3.MonsterHandler.java处理请求信息4.monster_addUI.jsp添加妖怪界面5.单元测试 3.保存妖怪信息1.MonsterHandler.java…

【软件开发规范篇】Git分支使用规范

作者介绍&#xff1a;本人笔名姑苏老陈&#xff0c;从事JAVA开发工作十多年了&#xff0c;带过刚毕业的实习生&#xff0c;也带过技术团队。最近有个朋友的表弟&#xff0c;马上要大学毕业了&#xff0c;想从事JAVA开发工作&#xff0c;但不知道从何处入手。于是&#xff0c;产…

windows驱动开发-中断(一)

中断是windows中最难的一部分&#xff0c;这是因为中断本身属于操作系统的一部分&#xff0c;理解了中断和内存&#xff0c;对整个系统也就了解了。 中断部分会先从中断优先级、中断处理、中断服务例程入手&#xff0c;大概讲述一下中断的概念&#xff1b;接着从中断的一般实现…

springboot 集成 activemq

文章目录 一&#xff1a;说明二&#xff1a;e-car项目配置1 引入activemq依赖2 application启动类配置消息监听3 application.yml配置4 MQConfig.java 配置类5 ecar 项目中的监听6 junit 发送消息 三&#xff1a;tcm-chatgpt项目配置5 MQListener.java 监听消息 三 测试启动act…

Docker② —— Cgroups详解

1. 概述 Cgroups 的全称是control groups&#xff0c;cgroups为每种可以控制的资源定义了一个子系统。Cgroups分为三个部分&#xff1a; cgroup 本身&#xff1a;对进程进行分组hierarchy&#xff1a;将 cgroup 形成树形结构subsystem&#xff1a;真正起到限制作用的部组件 cp…

【vscode】2024最新!vscode云端配置同步方案:code settings sync

小tian最近对电脑进行了系统重装&#xff0c;结果vscode相关配置和插件都没有保存记录&#xff0c;还好公司电脑里还有。痛定思痛&#xff0c;决定写一篇vscode云端同步配置方案&#xff0c;以作记录和分享~ 步骤一&#xff1a;安装vscode插件&#xff1a;code settings sync …

云贝餐饮连锁V2-2.9.9源码

云贝餐饮连锁V2独立版、版本更新至2.9.9&#xff0c;小程序、公众号版本&#xff0c;全插件&#xff0c;公众号小程序端&#xff0c;独立版&#xff1b; 带商家端&#xff0c;修复收银台、排队点餐、堂食点餐&#xff1b;最新版更新 搭建环境教程: 系统环境&#xff1a;CentO…

【04】JAVASE-循环语句【从零开始学JAVA】

Java零基础系列课程-JavaSE基础篇 Lecture&#xff1a;波哥 Java 是第一大编程语言和开发平台。它有助于企业降低成本、缩短开发周期、推动创新以及改善应用服务。如今全球有数百万开发人员运行着超过 51 亿个 Java 虚拟机&#xff0c;Java 仍是企业和开发人员的首选开发平台。…

算法学习笔记Day9——动态规划基础篇

一、介绍 本文解决几个问题&#xff1a;动态规划是什么&#xff1f;解决动态规划问题有什么技巧&#xff1f;如何学习动态规划&#xff1f; 1. 动态规划问题的一般形式就是求最值。动态规划其实是运筹学的一种最优化方法&#xff0c;只不过在计算机问题上应用比较多&#xff…

微信小程序小游戏开发,微信开发者工具提示该目录下的项目(wxapp2)已在工具中创建,怎么办

微信小程序小游戏开发&#xff0c;微信开发者工具提示该目录下的项目&#xff08;wxapp2&#xff09;已在工具中创建&#xff0c;怎么办 情况描述&#xff0c; 导入一个项目的时候&#xff0c;导入成了小游戏项目了 想换成小游戏项目&#xff0c;变不了了&#xff0c;提示 “…

未来已来:解锁AGI的无限潜能与挑战

未来已来&#xff1a;解锁AGI的无限潜能与挑战 引言 假设你有一天醒来&#xff0c;发现你的智能手机不仅提醒你今天的日程&#xff0c;还把你昨晚做的那个奇怪的梦解释了一番&#xff0c;并建议你可能需要减少咖啡摄入量——这不是科幻电影的情节&#xff0c;而是人工通用智能…

解决Milvus官网提供的单机版docker容器无法启动,以及其它容器进程与Milvus容器通信实现方案【Milvus】【pymilvus】【Docker】

文章目录 问题预备知识方案获取pymilvus获取milvus 实例多容器通信 问题 我的需求是做混合检索单机版可以满足&#xff0c;要走Docker容器部署&#xff0c;还需要和另一个容器中的程序做通信。官方文档提供的Milvus安装启动Milvus方案&#xff0c;见文档&#xff1a;传送门 我…

wlan二层直连组网实验(ensp)

目录 1. VLAN 端口类型及参数设计2. IP 地址规划3. WLAN数据规划(1) DHCP服务器配置(2) AC 源接口地址、认证方式配置(3) AP 组的创建(4) 创建域管理模板、国家码认证(5) 创建安全模板(6) 创建SSID模板(7) 创建VAP模板(8) AP组绑定模板(9) 查看&#xff1a; 1. VLAN 端口类型及…