27. UE5 RPG同步面板属性(三)

news/2024/6/15 16:45:49/文章来源:https://blog.csdn.net/qq_30100043/article/details/137171607

在前两篇中,我们在C++中实现了对GameplayTag的创建,并且创建DataAsset存储数据,按照之前的规划:

  1. 首先我们需要通过c++去实现创建GameplayTag,这样可以在c++和UE里同时获取到Tag
  2. 创建一个DataAsset类,用于设置tag对应的属性和显示内容
  3. 创建AttributeMenuWidgetController实现对应逻辑

我们将在这一篇里实现对AttributeMenuWidgetController创建,可以将数据从AS里同步到UI上面。

创建AttributeMenuWidgetController

首先基于之前的创建的WidgetController的基类创建一个子类
在这里插入图片描述
将其命名为AttributeMenuWidgetController
在这里插入图片描述
覆盖一下父类的初始化属性函数和构件委托的函数,我们后续将在这两个函数内实现对属性面板的属性的广播。
我们并创建了一个委托AttributeInfoDelegate这个委托设置了BlueprintAssignable修饰符,那么就可以在蓝图里面作为回调绑定使用。
AttributeInfo参数只能在UE面板编辑,我们在上一篇添加了对应的Tag和属性名描述,作为显示内容,如果需要本地化,可以添加多个,切换中英文等其它语种的显示。

// 版权归暮志未晚所有。#pragma once#include "CoreMinimal.h"
#include "UI/WidgetController/MyWidgetController.h"
#include "AttributeMenuWidgetController.generated.h"class UAttributeInfo;
struct FMyAttributeInfo;
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FAttibuteInfoSignature, const FMyAttributeInfo&, Info);/*** */
UCLASS(BlueprintType, Blueprintable)
class AURA_API UAttributeMenuWidgetController : public UMyWidgetController
{GENERATED_BODY()public:virtual void BindCallbacksToDependencies() override;virtual void BroadcastInitialValues() override;UPROPERTY(BlueprintAssignable, Category="GAS|Attributes")//设置BlueprintAssignable可以在蓝图作为委托绑定监听FAttibuteInfoSignature AttributeInfoDelegate;protected:UPROPERTY(EditDefaultsOnly)//EditDefaultsOnly只能在UE面板编辑TObjectPtr<UAttributeInfo> AttributeInfo;
};

这两个函数我们将在后续对其内容进行实现。

在HUD设置Controller

之前,我们在HUD类设置了创建OverlayWidgetController,用于进入游戏时,主界面生命值和法力值的更新。
相应的,我们也将实现对AttributeMenuWidgetController的添加,作为AttributeMenuWidgetController的单例承载。
我们在HUD类里面创建一个承载它实例的变量,并添加一个获取方法

UAttributeMenuWidgetController* GetAttributeMenuWidgetController(const FWidgetControllerParams& WCParams);UPROPERTY()TObjectPtr<UAttributeMenuWidgetController> AttributeMenuWidgetController;UPROPERTY(EditAnywhere)TSubclassOf<UAttributeMenuWidgetController> AttributeMenuWidgetControllerClass;

函数的实现这里,其实就是保证只实例化一次,后面的都复用它即可

UAttributeMenuWidgetController* AMyHUD::GetAttributeMenuWidgetController(const FWidgetControllerParams& WCParams)
{if(AttributeMenuWidgetController == nullptr){AttributeMenuWidgetController = NewObject<UAttributeMenuWidgetController>(this, AttributeMenuWidgetControllerClass);AttributeMenuWidgetController->SetWidgetControllerParams(WCParams);AttributeMenuWidgetController->BindCallbacksToDependencies(); //绑定监听数值变化}return AttributeMenuWidgetController;
}

编译,打开UE,创建一个基于AttributeMenuWidgetController类的蓝图,这里创建蓝图的原因是我们需要通过蓝图去设置AttributeInfo的数据。
在这里插入图片描述
将我们之前创建的属性数据设置上去
在这里插入图片描述
接着到HUD蓝图这里,将AttributeMenuWidgetControllerClass类设置上蓝图。
在这里插入图片描述
这样,在项目运行得时候,这两个Controller都会被创建出来,去使用。

接下来就是需要考虑如何在UI里面去获取到Controller,我们之前对OverlayWidgetController的获取是在创建UI的时候,在Widget的事件里面通过蓝图设置过去的,但是在属性面板内,层级太多,我们一层层的设置过去太过于麻烦,下面,我们将使用一个新的方式能够在全局蓝图里获取Controller。

创建蓝图函数库获取Controller

我们创建一个蓝图函数库,可以通过静态函数在任意位置获取到对应的Controller,这样可以让结构更加的清晰,也更加方便。

首先打开UE,创建一个新的c++类,这个类继承至BlueprintFunctionLibrary
在这里插入图片描述
设置好名称
在这里插入图片描述
编辑器打开,创建两个静态函数,分别用于获取OverlayWidgetController和AttributeMenuWidgetController
BlueprintPure 为去掉在蓝图内使用时的执行接口,这样,我们不需要调用,也可以直接从节点获取返回。

// 版权归暮志未晚所有。#pragma once#include "CoreMinimal.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "MyAbilitySystemBlueprintLibrary.generated.h"class UAttributeMenuWidgetController;
class UOverlayWidgetController;
/*** */
UCLASS()
class AURA_API UMyAbilitySystemBlueprintLibrary : public UBlueprintFunctionLibrary
{GENERATED_BODY()public:UFUNCTION(BlueprintPure, Category="MyAbilitySystemLibrary|WidgetController")static UOverlayWidgetController* GetOverlayWidgetController(const UObject* WorldContextObject);UFUNCTION(BlueprintPure, Category="MyAbilitySystemLibrary|WidgetController")static UAttributeMenuWidgetController* GetAttributeMenuWidgetController(const UObject* WorldContextObject);
};

在函数实现这里,我们通过函数,从世界上下文的对象获取到本地的PlayerController,然后根据PlayerController获取到所需的配置项,再从HUD身上的函数获取Controller。
这里比较有意思的就是通过在一个世界上下文的对象可以获取到它所处的世界内的PlayerController。

// 版权归暮志未晚所有。#include "AbilitySystem/MyAbilitySystemBlueprintLibrary.h"#include "Kismet/GameplayStatics.h"
#include "Player/PlayerStateBase.h"
#include "UI/HUD/MyHUD.h"
#include "UI/WidgetController/MyWidgetController.h"UOverlayWidgetController* UMyAbilitySystemBlueprintLibrary::GetOverlayWidgetController(const UObject* WorldContextObject)
{//获取到playerController, 需要传入一个世界空间上下文的对象,用于得到对应世界中的PC列表,0为本地使用的PCif(APlayerController* PC = UGameplayStatics::GetPlayerController(WorldContextObject, 0)){//从PC获取到HUD,我们就可以从HUD获得对应的Controllerif(AMyHUD* HUD = Cast<AMyHUD>(PC->GetHUD())){APlayerStateBase* PS = PC->GetPlayerState<APlayerStateBase>();UAbilitySystemComponent* ASC = PS->GetAbilitySystemComponent();UAttributeSet* AS = PS->GetAttributeSet();const FWidgetControllerParams WidgetControllerParams(PC, PS, ASC, AS);return HUD->GetOverlayWidgetController(WidgetControllerParams);}}return nullptr;
}UAttributeMenuWidgetController* UMyAbilitySystemBlueprintLibrary::GetAttributeMenuWidgetController(const UObject* WorldContextObject)
{//获取到playerController, 需要传入一个世界空间上下文的对象,用于得到对应世界中的PC列表,0为本地使用的PCif(APlayerController* PC = UGameplayStatics::GetPlayerController(WorldContextObject, 0)){//从PC获取到HUD,我们就可以从HUD获得对应的Controllerif(AMyHUD* HUD = Cast<AMyHUD>(PC->GetHUD())){APlayerStateBase* PS = PC->GetPlayerState<APlayerStateBase>();UAbilitySystemComponent* ASC = PS->GetAbilitySystemComponent();UAttributeSet* AS = PS->GetAttributeSet();const FWidgetControllerParams WidgetControllerParams(PC, PS, ASC, AS);return HUD->GetAttributeMenuWidgetController(WidgetControllerParams);}}return nullptr;
}

然后编译,我们在UE打开Overlay的UI,就可以直接右键获取,下面的事OverlayWidget里面的函数,上面的则是静态函数
在这里插入图片描述
我们直接将之前设置方式修改,
在这里插入图片描述
也能够实现之前的效果。

接着,我们在WBP_AttributeMenu里面使用静态函数获取到AttributeMenuWidgetController设置
在这里插入图片描述
可以做一下测试,打印一下Controller的名称
在这里插入图片描述
运行项目,点击打开属性面板,查看是否有名称打印。
在这里插入图片描述
这里有个问题,我们在设置OverlayWidgetController时,是在C++内,初始化UI属性显示的。

在这里插入图片描述
在函数内,执行逻辑是:

  1. OverlayWidget->SetWidgetController(OverlayWidgetController); //设置用户控件的控制器层
  2. 设置属性后,会调用WidgetControllerSet();执行函数,这个在UI里面可以
    在这里插入图片描述
    Widget会在WidgetControllerSet()执行后,进行Controller设置并绑定监听。
    在这里插入图片描述
  3. 接着就会执行OverlayWidgetController->BroadcastInitialValues();在函数内进行广播将数据广播出去实现了数据在UI上面初始显示。

但是属性面板是动态创建的,所以我们需要将BroadcastInitialValues设置为蓝图可调用
在这里插入图片描述
然后打开WBP_AttributeMenu里面,等构造完成后使用蓝图调用BroadcastInitialValues函数。
在这里插入图片描述
Event Construct事件是在自身和自己的子元素都创建完成后才会被调用,我在子元素的Event Construct后面打印11111111,在WBP_AttributeMenu里面打印Hello,发现在最后打印了Hello,证明我们在使用蓝图调用BroadcastInitialValues函数时,子元素可以在Event Construct里面绑定监听委托,即可实现初始化。
在这里插入图片描述
我说这么多的原因在于大家一定要了解清楚引擎的运行逻辑,这样才能更好的梳理逻辑学习以及使用内置的内容。

到这里,我们创建了AttributeMenuWidgetController,并实现了在Widget内的任意位置获取它,由于篇幅太长,我将在下一篇里,对AttributeMenuWidgetController内部进行实现,实现数据更新,直接同步到UI上面。

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

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

相关文章

(补充)Java项目实战笔记--基于SpringBoot3.0开发仿12306高并发售票系统--(二)项目实现-第六篇-(高级篇)实现高性能高并发

本章目录&#xff08;接上篇&#xff09; 六、使用MQ对请求做异步削峰处理&#xff0c;解决吞吐量问题1.购票时序图演进2.RocketMQ初体验1.下载2.启动NameServer和Broker3.测试消息收发 3.RocketMQ控制台的使用4.**使用RocketMQ将购票流程一分为二**5.为同转异增加logId&#x…

【Linux】图文详解Xshell远程连接服务器:以Amazon EC2 VPS为例

文章目录 问题描述解决方案Q&A 问题描述 本地cmd或powershell使用ssh -i “your.pem” user_nameip_address是可以登录Amazon EC2云服务器的。 然而&#xff0c;当使用XShell以SSH加载PEM文件方式登录亚马逊EC2云服务器&#xff0c;一直出现输入密码的问题&#xff0c;如…

Fastjson配置消息转换器(时间格式问题)

问题&#xff1a; 我们可以看见&#xff0c;日期的格式有点问题。 由于ArticleListVO类的createTime成员变量是Date类型&#xff0c;默认是由java的Jackson来处理&#xff0c;使用 ISO-8601 规范来处理日期时间格式。ISO-8601 是一种国际标准的日期时间表示法&#xff0c;例如&…

是否应该升级到ChatGPT 4.0?深度对比ChatGPT 3.5与4.0的差异

如果只是想简单地体验AI的魅力&#xff0c;感受大模型的独特之处&#xff0c;或是玩一玩文字游戏&#xff0c;那么升级至ChatGPT 4.0可能并非必需。然而&#xff0c;若你期望将AI作为提升工作学习效率的得力助手&#xff0c;那么我强烈建议你升级到ChatGPT 4.0。 如果你不知道…

【网站项目】面向社区健康服务的医疗平台

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

从原理图到PCB全过程(嘉立创)1

1 将已经画好的原理图更新到PCB中&#xff08;点击应用修改&#xff09; 2 一开始PCB是杂乱的&#xff0c;需要回到原理图&#xff0c;框选各个模块&#xff0c;然后按住CtrlShiftX会自动在PCB显示这个部分&#xff0c;然后把各个部分分开 3 PCB画板需要有板框(嘉立创每个月都i…

Go语言学习Day6:数组与切片

名人说&#xff1a;莫愁千里路&#xff0c;自有到来风。 ——钱珝 创作者&#xff1a;Code_流苏(CSDN)&#xff08;一个喜欢古诗词和编程的Coder&#x1f60a;&#xff09; 目录 1. 数组① 什么是数组② 数组的声明③ 初始化数组的几种方式④ 遍历数组元素⑤ 数组为值类型⑥ 数…

A New Image Contrast Enhancement Algorithmusing Exposure Fusion Framework

Abstract 弱光图像由于能见度低&#xff0c;不利于人类观察和计算机视觉算法。为了解决这一问题&#xff0c;人们提出了许多图像增强技术&#xff0c;但现有的方法不可避免地会出现对比度增强不足和过度增强的问题。在本文中&#xff0c;我们提出了一种图像对比度增强算法来提…

瑞吉外卖实战学习--8、人员编辑更新

人员编辑更新 前言1、进入编辑窗口需要先获取用户信息2、通过上篇文章的update的方法来改变数据3、测试效果 前言 1、进入编辑窗口需要先获取用户信息 通过注解PathVariable 来获取路径需要携带的id然后赋值到路径上&#xff0c;再通过id查询用户信息 /*** 通过id查询用户信…

VUE3极速上手手册

文章目录 Vue3简介一、整体认识Vue3项目1、创建Vue3工程2、主要工程结构 二、数据双向绑定1、vue2语法的双向绑定2、OptionsAPI和CompositionAPI3、Vue3中的数据双向绑定3.1 ref定义基础类型响应式数据3.2 reactive定义对象型响应式数据3.3 ref对比reactive3.4 标签的ref属性3.…

Android 开发 Spinner setSelection 不起作用

问题 Android 开发 Spinner setSelection 不起作用 详细问题 笔者进行Android项目开发&#xff0c;根据上一个页面用户选择数据&#xff0c;显示当前页面Spinner选项&#xff0c;调用 Spinner setSelection 不起作用。 相关java代码 spinner.setAdapter(adapter); …

uniapp点击按钮连接wifi?

<view><button class"but" bindtap"connectToWifi">点击连接WiFi</button> </view> js: Page({// 页面数据data: {wifiConnected: false},onLoad: function () {this.checkWifiPermission();},// 检查 WiFi 权限checkWif…

不同设备使用同一个Git账号

想要在公司和家里的电脑上用同一个git账号来pull, push代码 1. 查看原设备的用户名和邮箱 第1种方法&#xff0c; 依次输入 git config user.name git config user.email第2种方法&#xff0c; 输入 cat ~/.gitconfig2. 配置新设备的用户名和邮箱 用户名和邮箱与原设备保持…

uniApp——零基础App的快速开发记录

公司需要使用移动端App来接受云平台的数据&#xff0c;记录一下学习过程。因水平有限&#xff0c;在学习的过程中不能完整、准确、全面的发现错误&#xff0c;如有错误&#xff0c;请评论指教&#xff0c;谢谢&#xff01; 需求分析 总体需求目标&#xff1a;开发一款android的…

文件传输升级!如何让你的MacBook与安卓设备快速共享大文件?

在现代工作环境中&#xff0c;跨设备、跨平台的文件传输已成为日常办公不可避免的一部分。尤其是MacBook和安卓手机之间的大文件传输&#xff0c;由于两者系统的差异&#xff0c;可能会遇到一些效率上的挑战。为了优化这一过程&#xff0c;以下是一些提升传输效率的新技巧。 1&…

搜索与图论——Prim算法求最小生成树

在最小生成树问题里&#xff0c;正边和负边都没问题 朴素版prim算法 时间复杂度O(n^2) 生成树&#xff1a;每一次选中的t点&#xff0c;它和集合的距离对应的那条边&#xff0c;就是生成树的一条边 算法流程和dijkstra算法非常相似 #include<iostream> #include<cs…

稀碎从零算法笔记Day33-LeetCode:生命游戏

今天是“耶稣受难人”&#xff0c;笔者给自己放了天假hhh 且慢&#xff0c;还是会写一点的。 根据 百度百科 &#xff0c; 生命游戏 &#xff0c;简称为 生命 &#xff0c;是英国数学家约翰何顿康威在 1970 年发明的细胞自动机。 题型&#xff1a;矩阵、原地实现、位运算 链…

Pytorch for training1——read data/image

blog torch.utils.data.Dataset create dataset with class torch.utils.data.Dataset automaticly import torch from torch.utils.data import Datasetclass MyDataset(Dataset):def __init__(self, data):self.data datadef __getitem__(self, index):# 根据索引获取样本…

紫光展锐P7885核心板详细参数介绍_5G安卓智能模块开发方案

紫光展锐P7885核心板采用了先进的6nm EUV制程工艺&#xff0c;集成了高性能的应用处理器和金融级安全解决方案&#xff0c;为用户带来了全新的性能体验。 P7885核心板搭载了先进的6nm制程工艺SoC P7885&#xff0c;其中包含四核A76和四核A55&#xff0c;主频可达2.7Ghz&#xf…

计算机网络面试问题(一)

1.在浏览器中输⼊URL并按下回⻋之后会发⽣什么 2.TCP三次握⼿的过程,为什么三次握手 TCP&#xff08;传输控制协议&#xff09;的三次握⼿是建⽴⽹络连接的过程&#xff0c;确保通信双⽅能够正确地进⾏数据传输。 第⼀次握⼿&#xff08;SYN&#xff09;&#xff1a; 客户端&am…