9. UE5 RPG创建UI(下)

在上一篇文章里,制作了显示血量和蓝量的ui,并且还将ui和获取数据使用的控制器层创建出来并初始化成功。现在只有主用户控件上面被添加了控制器层,还未给每个用户控件赋予控制器层。接下来要实现对属性的广播功能,在属性值变化的时候,能够在蓝图中获取到数值的变化并更新到用户控件上面。

使用广播设置初始值

首先在控制器层里面添加一个函数

virtual void BroadcastInitialValues();

这个函数用于广播初始化函数。我们上一文章里基于控制器层类创建了一个子类,专门用于Overlay的,在里面复写这个函数

public:virtual void BroadcastInitialValues() override;

接下来就是重点,我们将以委托的形式设置每个属性的广播功能,这里就需要用到委托对应的函数。不清楚的小伙伴可以看下这里
一文理解透UE委托Delegate

这里使用了动态多播委托函数绑定,下面是实现,委托的函数DelegateName 首字母必须以F开头。
一下是定义了获取血量的委托,返回一个参数就是当前的血量浮点数。

DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnHealthChangedSignature,float, NewHealth);

接下来定义一个变量,实现对回调的引用

	UPROPERTY(BlueprintAssignable, Category="GAS|Attributes")FOnHealthChangedSignature FOnHealthChanged;

然后最后通过广播形式将数据广播出去

FOnHealthChanged.Broadcast(50.f);

当前,我们需要实际的血量数值,所以广播出去的就是从AttributeSet里面获取到的值

	const UAttributeSetBase* AttributeSetBase = CastChecked<UAttributeSetBase>(AttributeSet);OnHealthChanged.Broadcast(AttributeSetBase->GetHealth());OnMaxHealthChanged.Broadcast(AttributeSetBase->GetMaxHealth());

函数有了,需要有个地方调用,实例化这个函数我们是在HUD类里面实例化的,那就在实例化完成后面调用。也就是MyHUD.cpp里面的InitOverlay()里面,这个顺序不能错,首先需要设置控制器层,这时会触发蓝图里面可以调用的设置控制器层回调通知,用户控件会以此来绑定广播回调。然后再广播初始的值,用户控件里就实现了对值的初始化设置。

	OverlayWidgetController = GetOverlayWidgetController(WidgetControllerParams); //获取控制器层OverlayWidget->SetWidgetController(OverlayWidgetController); //设置用户控件的控制器层OverlayWidgetController->BroadcastInitialValues(); //初始化广播

这样设置完成以后,打开UE,在设置的WBP_Overlay里面,在上一章最后设置的设置完成控制器层对象后的回调中,将控制器层对象传递给需要显示的用户控件节点。
在这里插入图片描述
做到这一步,我们在需要同步数据的UI上面就都可以获取到控制器层对象。接着,我们要将Overlay的控制器层类公开给蓝图。

UCLASS(BlueprintType, Blueprintable)
class AURA_API UOverlayWidgetController : public UMyWidgetController

直接在类上面的UCLASS()内添加上两个参数。
BlueprintType 将此类公开为可用于蓝图中的变量的类型。
Blueprintable 将此类公开为用于创建蓝图的可接受基类。默认为NotBlueprintable,除非继承时就并非如此。此说明符由子类继承。
设置完成这两项,我们就可以把控制器层对象转换为控制器层类的实例了。
为了方便后面的工作,推荐不要直接使用c++的类,通过蓝图创建一个c++的基类去使用。

在这里插入图片描述
将HUD里面的控制器层类的引用修改成蓝图的。
在这里插入图片描述
在进度条的蓝图基类WBP_GlobeProgressBar中添加一个函数,用于设置进度条百分比,接收一个参数
在这里插入图片描述
之前在OverlayWidget里面,将在c++里面生成的控制器层对象传递给了对应的用户组件。我们在血量控件中,也可以使用WidgetControllerSet通知,获得通知后将变量保存。
在这里插入图片描述
之前我们在OverlayWidgetController里面添加了对血量和最大血量的广播,所以,在蓝图里,我们可以实现绑定血量变化。在数值变化后,可以通过调用设置进度条百分比进行进度条设置。
在这里插入图片描述
顺便也绑定最大血量。
在这里插入图片描述

监听数值的变化

上面我们实现通过广播的形式对用户控件内的值进行初始化,还未实现对数值变化后触发广播更新ui显示。
我们需要通过使用AbilitySystemComponent->GetGameplayAttributeValueChangeDelegate()来注册一个监听一个值的变化,如果监听的数值变化了接着将变化后的数值进行广播。比如下面就是监听血量属性是否变化

AbilitySystemComponent->GetGameplayAttributeValueChangeDelegate(AttributeSetBase->GetHealthAttribute())

为了区分开,我们需要在控制器层类里面新加一个函数,专门用来注册监听数据变化回调的。

virtual void BindCallbacksToDependencies() override;

接着创建两个保护类型的函数,用于监听到数值变化后的回调函数

protected:void HealthChanged(const FOnAttributeChangeData& Data) const;void MaxHealthChanged(const FOnAttributeChangeData& Data) const;

接着,在绑定监听函数内实现监听:

void UOverlayWidgetController::BindCallbacksToDependencies()
{const UAttributeSetBase* AttributeSetBase = CastChecked<UAttributeSetBase>(AttributeSet);AbilitySystemComponent->GetGameplayAttributeValueChangeDelegate(AttributeSetBase->GetHealthAttribute()).AddUObject(this, &UOverlayWidgetController::HealthChanged);AbilitySystemComponent->GetGameplayAttributeValueChangeDelegate(AttributeSetBase->GetMaxHealthAttribute()).AddUObject(this, &UOverlayWidgetController::MaxHealthChanged);}

在数值变化时,就会触发去调用Changed函数,我们只需要在changed函数内,将数值广播给蓝图即可。

void UOverlayWidgetController::HealthChanged(const FOnAttributeChangeData& Data) const
{OnHealthChanged.Broadcast(Data.NewValue);
}void UOverlayWidgetController::MaxHealthChanged(const FOnAttributeChangeData& Data) const
{OnMaxHealthChanged.Broadcast(Data.NewValue);
}

最后,需要找一个地方调用监听函数绑定,我选在了HUD对初始化数值调用之后

	OverlayWidget->SetWidgetController(OverlayWidgetController); //设置用户控件的控制器层OverlayWidgetController->BroadcastInitialValues(); //初始化广播的值OverlayWidgetController->BindCallbacksToDependencies(); //绑定监听数值变化

接下来,按照之前的方式将蓝的设置添加上,这里不在编写实现,因为和血量的方式一行按照上面一步步来即可。下面列一下代码。

控制器层代码

MyWidgetController.h

// 版权归暮志未晚所有。#pragma once#include "CoreMinimal.h"
#include "AbilitySystemComponent.h"
#include "UObject/NoExportTypes.h"
#include "MyWidgetController.generated.h"class UAttributeSet;
class UAbilitySystemComponent;/*** 生成用户控件控制器的结构体,需要四项内容去生成。*/
USTRUCT(BlueprintType)
struct FWidgetControllerParams
{GENERATED_BODY()FWidgetControllerParams(){}FWidgetControllerParams(APlayerController* PC, APlayerState* PS, UAbilitySystemComponent* ASC, UAttributeSet* AS): PlayerController(PC),PlayerState(PS),AbilitySystemComponent(ASC),AttributeSet(AS){}UPROPERTY(EditAnywhere, BlueprintReadWrite)TObjectPtr<APlayerController> PlayerController = nullptr;UPROPERTY(EditAnywhere, BlueprintReadWrite)TObjectPtr<APlayerState> PlayerState = nullptr;UPROPERTY(EditAnywhere, BlueprintReadWrite)TObjectPtr<UAbilitySystemComponent> AbilitySystemComponent = nullptr;UPROPERTY(EditAnywhere, BlueprintReadWrite)TObjectPtr<UAttributeSet> AttributeSet = nullptr;
};/*** 用户控件控制器层,用户控件可从控制器层更新数据显示,以及为控制器层提供输入。*/
UCLASS()
class AURA_API UMyWidgetController : public UObject
{GENERATED_BODY()public:UFUNCTION(BlueprintCallable)void SetWidgetControllerParams(const FWidgetControllerParams& WCParams);virtual void BroadcastInitialValues(); //广播初始化的值virtual void BindCallbacksToDependencies(); //绑定数值变动后回调的广播protected:UPROPERTY(BlueprintReadOnly, Category="WidgetController")TObjectPtr<APlayerController> PlayerController;UPROPERTY(BlueprintReadOnly, Category="WidgetController")TObjectPtr<APlayerState> PlayerState;UPROPERTY(BlueprintReadOnly, Category="WidgetController")TObjectPtr<UAbilitySystemComponent> AbilitySystemComponent;UPROPERTY(BlueprintReadOnly, Category="WidgetController")TObjectPtr<UAttributeSet> AttributeSet;};

MyWidgetController.cpp

// 版权归暮志未晚所有。#include "UI/WidgetController/MyWidgetController.h"void UMyWidgetController::SetWidgetControllerParams(const FWidgetControllerParams& WCParams)
{PlayerController = WCParams.PlayerController;PlayerState = WCParams.PlayerState;AbilitySystemComponent = WCParams.AbilitySystemComponent;AttributeSet = WCParams.AttributeSet;
}void UMyWidgetController::BroadcastInitialValues()
{
}void UMyWidgetController::BindCallbacksToDependencies()
{
}

OverlayWidgetController.h

// 版权归暮志未晚所有。#pragma once#include "CoreMinimal.h"
#include "UI/WidgetController/MyWidgetController.h"
#include "OverlayWidgetController.generated.h"DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnHealthChangedSignature,float, NewHealth);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnMaxHealthChangedSignature,float, NewMaxHealth);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnManaChangedSignature,float, NewMana);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnMaxManaChangedSignature,float, NewMaxMana);/*** 屏幕覆盖用户控件控制器层基类,继承与用户控件控制器*/
UCLASS(BlueprintType, Blueprintable)
class AURA_API UOverlayWidgetController : public UMyWidgetController
{GENERATED_BODY()public:virtual void BroadcastInitialValues() override;virtual void BindCallbacksToDependencies() override;UPROPERTY(BlueprintAssignable, Category="GAS|Attributes")FOnHealthChangedSignature OnHealthChanged;UPROPERTY(BlueprintAssignable, Category="GAS|Attributes")FOnMaxHealthChangedSignature OnMaxHealthChanged;UPROPERTY(BlueprintAssignable, Category="GAS|Attributes")FOnManaChangedSignature OnManaChanged;UPROPERTY(BlueprintAssignable, Category="GAS|Attributes")FOnMaxManaChangedSignature OnMaxManaChanged;protected:void HealthChanged(const FOnAttributeChangeData& Data) const;void MaxHealthChanged(const FOnAttributeChangeData& Data) const;void ManaChanged(const FOnAttributeChangeData& Data) const;void MaxManaChanged(const FOnAttributeChangeData& Data) const;
};

OverlayWidgetController.cpp

// 版权归暮志未晚所有。#include "UI/WidgetController/OverlayWidgetController.h"#include "AbilitySystem/AttributeSetBase.h"void UOverlayWidgetController::BroadcastInitialValues()
{const UAttributeSetBase* AttributeSetBase = CastChecked<UAttributeSetBase>(AttributeSet);OnHealthChanged.Broadcast(AttributeSetBase->GetHealth());OnMaxHealthChanged.Broadcast(AttributeSetBase->GetMaxHealth());OnManaChanged.Broadcast(AttributeSetBase->GetMana());OnMaxManaChanged.Broadcast(AttributeSetBase->GetMaxMana());
}void UOverlayWidgetController::BindCallbacksToDependencies()
{const UAttributeSetBase* AttributeSetBase = CastChecked<UAttributeSetBase>(AttributeSet);AbilitySystemComponent->GetGameplayAttributeValueChangeDelegate(AttributeSetBase->GetHealthAttribute()).AddUObject(this, &UOverlayWidgetController::HealthChanged);AbilitySystemComponent->GetGameplayAttributeValueChangeDelegate(AttributeSetBase->GetMaxHealthAttribute()).AddUObject(this, &UOverlayWidgetController::MaxHealthChanged);AbilitySystemComponent->GetGameplayAttributeValueChangeDelegate(AttributeSetBase->GetManaAttribute()).AddUObject(this, &UOverlayWidgetController::ManaChanged);AbilitySystemComponent->GetGameplayAttributeValueChangeDelegate(AttributeSetBase->GetMaxManaAttribute()).AddUObject(this, &UOverlayWidgetController::MaxManaChanged);}void UOverlayWidgetController::HealthChanged(const FOnAttributeChangeData& Data) const
{OnHealthChanged.Broadcast(Data.NewValue);
}void UOverlayWidgetController::MaxHealthChanged(const FOnAttributeChangeData& Data) const
{OnMaxHealthChanged.Broadcast(Data.NewValue);
}void UOverlayWidgetController::ManaChanged(const FOnAttributeChangeData& Data) const
{OnManaChanged.Broadcast(Data.NewValue);
}void UOverlayWidgetController::MaxManaChanged(const FOnAttributeChangeData& Data) const
{OnMaxManaChanged.Broadcast(Data.NewValue);
}

多人模式调试UI显示

在运行下拉中,将人数修改为2
在这里插入图片描述
然后将客户端同时作为服务器使用
在这里插入图片描述
接着会发现运行了两个实例,并且拥有相同的血量和蓝量
在这里插入图片描述
接下来,控制一个角色去吃掉药瓶,会发现她的血和蓝都产生了变化,而另外一个没有变化
在这里插入图片描述
到这里功能实现了。

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

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

相关文章

gitlab.rb主要配置

根据是否docker安装,进入挂载目录或安装目录 修改此文件,我一般是在可视化窗口中修改,有时候也在命令行手敲 将下面的配置复制到该文件中 external_url http://192.168.100.50 # nginx[listen_port] = 8000 (docker安装的这一行不需要,因为端口映射导致此处修改会导致访问…

2024茶饮品牌如何出圈,媒介盒子分析

随着新式茶饮的消费场景更加多元化&#xff0c;品类不断拓宽&#xff0c;消费者对新式茶饮的热情也是只增不减。居民可支配收入水平不断上升&#xff0c;居民消费升级为新式茶饮的发展也提供了良好基础&#xff0c;今天媒介盒子就来和大家聊聊&#xff1a;2024茶饮品牌如何出圈…

win10系统 pdf 文件无法正常预览

网上也看了不少办法&#xff0c;修改注册表什么的&#xff0c;太麻烦了&#xff0c;尝试了一下下载Adobe Acrobat Reader&#xff0c;安装后就可以成功预览显示啦&#xff01;对&#xff0c;就是这么简单&#xff01;Adobe Acrobat Reader下载链接&#xff1a;link

随机森林中每个树模型分裂时的特征选取方式

随机森林中每个树模型分裂时的特征选取方式 随机森林中每个树模型的每次分裂都是基于随机选取的特征子集进行分裂的。 具体来说&#xff0c;对于每个决策树&#xff0c;在每个节点的分裂过程中&#xff0c;随机森林算法会从原始特征集合中随机选择一个特征子集&#xff0c;然…

vulhub之Zabbix篇

CVE-2016-10134--SQL注入 一、漏洞介绍 zabbix是一款服务器监控软件&#xff0c;其由server、agent、web等模块组成&#xff0c;其中web模块由PHP编写&#xff0c;用来显示数据库中的结果。 漏洞环境 在vulhub靶场进行复现&#xff0c;启动zabbix 3.0.3。 二、复现步骤 1…

[代码随想录2]51单片机1T/12T到底怎么选?

为什么说51单片机怎么选&#xff1f; 时至今日&#xff0c;44年来51单片机自强不息&#xff0c;怎么描述它&#xff0c;堪称控制芯片中的王者&#xff01;&#xff01;&#xff01; 假设你21岁大学毕业进入社会&#xff0c;交社保交到今天恭喜你成功退休了214465 传统即标准5…

搭建一个简单的Spring Demo

要学习Spring 源码&#xff0c;一个是从Spring GitHub 上去down源码&#xff0c;然后倒入IDEA编译&#xff0c;但这种方法费时费力&#xff0c;如果你不需要对Spring 源码进行修改后&#xff0c;再编译的话&#xff0c;直接搭建一个Spring Demo 的Maven项目&#xff0c;引入Spr…

代理设计模式JDK动态代理CGLIB动态代理原理

代理设计模式 代理模式&#xff08;Proxy&#xff09;&#xff0c;为其它对象提供一种代理以控制对这个对象的访问。如下图 从上面的类图可以看出&#xff0c;通过代理模式&#xff0c;客户端访问接口时的实例实际上是Proxy对象&#xff0c;Proxy对象持有RealSubject的引用&am…

使用DockerFile构建镜像与镜像上传

目录 前言&#xff1a;为什么要使用Dockerfile &#xff1f; DockerFile构建镜像 1、构建基础对象 2、Dockerfile文件结构 3、构建Dockerfile文件镜像 二、镜像上传&#xff08;阿里云&#xff09; 前言&#xff1a;为什么要使用Dockerfile &#xff1f; 首先Dockerfile …

IOS-生命周期-Swift

目录 App生命周期应用状态未运行——Not running未激活——Inactive激活——Active后台——Backgroud挂起——Suspended 关系图生命周期方法相关方法注意在其他地方监听 ViewController生命周期UIView生命周期 App生命周期 应用状态 App主要有五种状态&#xff0c;分别是&…

Axure RP 9 动态面板

目录 轮播图绘制 多种方式登录 前言: 轮播图绘制、多种方式登录界面绘制 轮播图绘制 首先绘制一个动态面板 在概要区域选中动态面板进入State1面板中插入图片绘制 双击图片绘制插入本地图片&#xff0c;右键State1重复状态并更改图片 点击交互面板新建交互将需要添加…

RuoYi-Cloud本地部署--详细教程

文章目录 1、gitee项目地址2、RuoYi-Cloud架构3、本地部署3.1 下载项目3.2 idea打开项目3.3 启动nacos3.4 若依数据库准备3.5 启动redis3.6 修改nacos中的各个模块的配置文件3.7 启动ruoyi前端项目3.8 启动各个微服务模块 4、启动成功 1、gitee项目地址 https://gitee.com/y_p…

http网络编程——在ue5中实现文件传输功能

http网络编程在ue5中实现 需求&#xff1a;在unreal中实现下载功能&#xff0c;输入相关url网址&#xff0c;本地文件夹存入相应文件。 一、代码示例 1.Build.cs需要新增Http模块&#xff0c;样例如下。 PublicDependencyModuleNames.AddRange(new string[] { "Core&q…

锂电池SOC估计 | PatchTST时间序列模型锂电池SOC估计

目录 预测效果基本介绍程序设计参考资料 预测效果 基本介绍 锂电池SOC估计 | PatchTST时间序列模型锂电池SOC估计 采用新型PatchTST时间序列模型预测锂电池SOC&#xff0c;送锂电池数据集 可替换数据集&#xff0c;实现负荷预测、流量预测、降雨量预测、空气质量预测等其他多种…

k8s之ingress

ingress基于域名进行映射&#xff0c;把url(http https)的请求转发到service&#xff0c;再由service把请求转发到每一个pod ingress只要一个或者少量的公网ip或者LB&#xff0c;可以把多个http请求暴露到外网&#xff0c;七层反向代理 理解为service的service&#xff0c;是…

OSPF基础华为ICT网络赛道

6.1.OSPF协议概述 由协议之中OSPF(Open Shortest Path First,开放式最短路径优先)协议是使用场 景非常广泛的动态路由协议之一。 OSPF在RFC2328中定义&#xff0c;是一种基于链路状态算法的路由协议。 静态路由是由工程师手动配置和维护的路由条目&#xff0c;命令行简单明确…

年末怒赚一笔,程序员快码住!趁热接单

元旦已过&#xff0c;龙年将至。 有钱没钱&#xff0c;回家过年。 话说回来&#xff0c;年关将至&#xff0c;农历的2023即将落下帷幕。天气渐寒&#xff0c;你的钱包是否也让你心生寒意&#xff1f;年初立下的赚钱flag是否优雅地实现了? 如果flag都倒了&#xff0c;你先别…

【数据结构】从顺序表到ArrayList类

文章目录 1.线性表1.1线性表的概念2.顺序表2.1顺序表的概念2.2顺序表的实现2.3接口的实现(对数组增删查改操作)3.ArrayList简介4. ArrayList使用 4.1ArrayList的构造4.2 ArrayList的方法4.3 ArrayList的遍历 1.线性表 1.1线性表的概念 线性表&#xff08;linear list&#xf…

微信怎么设置自动回复?教程来咯!

自动回复信息 你有没有为了回复微信消息&#xff0c;中断工作进度&#xff0c;耽误了大量时间&#xff1f;或者错过了潜在客户&#xff1f;现在&#xff0c;我们的微信管理系统&#xff0c;可以帮助你在第一时间&#xff0c;实时回复用户消息。 01 # 通过好友自动打招呼# 我们…

CTF CRYPTO 密码学-5

题目名称&#xff1a;山岚 题目描述&#xff1a; 山岚 f5-lf5aa9gc9{-8648cbfb4f979c-c2a851d6e5-c} 解题过程&#xff1a; Step1&#xff1a;根据题目提示栅栏加密 分析 观察给出的密文发现有f、l、a、g等字符有规律的夹杂的密文中间&#xff0c;看出都是每3个字符的第1…