91. UE5 RPG 实现拖拽装配技能以及解除委托的绑定

在上一篇文章里,实现了通过选中技能,然后点击下方的装备技能插槽实现了技能的装配。为了丰富技能装配功能,在这一篇里,我们实现一下通过拖拽技能,实现拖拽功能,我们需要修改两个用户控件,一个就是技能按钮,我们需要在里面增加拖拽的功能,并且不能够与点击事件产生冲突,然后我们还需要在装配插槽增加拖拽放入的事件处理,在拖入技能装配插槽后,处理对应的逻辑。

具体操作流程,在拖拽技能时,技能能够根据装配的插槽来修改大小(主动技能插槽比被动技能插槽大),如果当前技能没有处于焦点,我们在拖拽时,会自动将其设置为焦点状态,然后触发拖拽后,可以装配的位置会高亮显示,当将技能拖拽到可放入的槽位时,拖拽的技能也会高亮,松手后,技能将应用到目标槽位,实现就用上一篇文章里的点击装配即可。

实现拖拽时对应装配部位可以高亮显示

首先,我们实现拖拽,可装配的槽位高亮显示,增加一个新的委托类型

DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FWaitForEquipSelectionSignature, const FGameplayTag&, InputTag, const FGameplayTag&, AbilityType); //等待技能装备选择

然后在技能面板控制器增加一个新的委托变量,用于装配栏监听

	UPROPERTY(BlueprintAssignable)FWaitForEquipSelectionSignature WaitForEquipSignature; //拖拽选中技能按钮后,广播可拖拽位置高亮显示

然后我们增加两个函数,用于在拖拽开始时调用,和在拖拽结束时调用

	UFUNCTION(BlueprintCallable)void EquipDragStart(); //装配技能按钮按下事件UFUNCTION(BlueprintCallable)void EquipDragEnd(); //装配技能按钮按下事件

这两个函数,主要用于广播委托,我们可以在蓝图里监听委托,根据委托设置是否需要显示隐藏高亮效果,委托广播的是输入标签和技能类型,在设置高亮时,我们可以根据这两个值来判断当前是否需要设置高亮

void USpellMenuWidgetController::EquipDragStart()
{const FRPGAbilityInfo Info = AbilityInfo->FindAbilityInfoForTag(SelectedAbility.Ability);const FGameplayTag& SelectedAbilityInputTag = GetRPGASC()->GetInputTagFromAbilityTag(SelectedAbility.Ability);WaitForEquipSignature.Broadcast(SelectedAbilityInputTag, Info.AbilityType);
}void USpellMenuWidgetController::EquipDragEnd()
{const FRPGGameplayTags GameplayTags = FRPGGameplayTags::Get();WaitForEquipSignature.Broadcast(GameplayTags.Abilities_None, GameplayTags.Abilities_Type_None);
}

然后我们在装配技能插槽里添加一个函数,用于设置当前插槽是否需要高亮,并判断输入标签如果一致,将无法高亮(没必要重复设置技能)
在这里插入图片描述
在高亮时,插槽显示一到光圈
在这里插入图片描述
这里我是编写了一个材质,可以根据运行时间调整亮度,类似于呼吸灯的效果
在这里插入图片描述
然后,我们在技能面板控制器里监听委托回调,调用设置高亮函数
在这里插入图片描述
设置高亮函数里,根据技能类型这里,根据匹配标签设置是否高亮,并将输入标签传入
在这里插入图片描述
然后将所有插槽调用自身的设置高亮
在这里插入图片描述

修改按钮

如果我们在一个用户控件里实现拖拽,并且,在里面添加了按钮,那么大概无法激活拖拽效果,因为鼠标事件将会被按钮阻挡,用户控件无法获取到对应的事件触发拖拽。

为了能够让拖拽事件顺利激活,这里我将按钮ui移出,使用一张图片替代
在这里插入图片描述
替换完成后,我们还是需要实现对应的按钮点击的效果,我们通过覆写鼠标相应的操作来模拟出鼠标点击按钮的效果。
在这里插入图片描述
在鼠标按下时,我们给定一个拖拽指针事件,当产生拖拽时,可以触发拖拽函数进行执行,然后我们添加了一个变量,用于定义鼠标被按下,并添加一个自定义事件,用来取消变量。
在这里插入图片描述
在自定义事件这里如果多次调用,在没到达延迟的时间时,将会重新延迟时间,在到达延迟时间后,将变量设置为false,在此时间后,抬起鼠标,将不会触发鼠标点击事件。
在这里插入图片描述
接下来就是处理鼠标悬停效果,我们可以通过鼠标进入和离开来判断鼠标是否悬停在UI上
在这里插入图片描述
后面设置就是指定一张图,然后在切换时,切换成对应的图片笔刷
在这里插入图片描述
接着就是在鼠标抬起事件里,我们其实就是复制了之前的鼠标点击事件,只是在前面添加了一个布尔判断,如果上面MouseDown变量被设置了false,就无法执行后面的点击事件
在这里插入图片描述
通过这样的一套操作,我们实现了模拟button的点击事件和鼠标悬停事件,如果还需要更细致的模拟,大家可以继续。

实现拖拽功能

接下来,到了重头戏了,就是拖拽功能,我们在技能按钮覆写发现拖动时,如果鼠标在按钮上按下,按照我们之前的配置,这个函数会被触发
在这里插入图片描述
在这个函数里,我们先判断是否是鼠标左键触发的拖拽
在这里插入图片描述
如果当前没有选中技能,我们需要激活当前技能的选中,(主要是为了让控制器保存我们拖拽的节点的技能标签,方便应用)

在这里插入图片描述
接着判断当前技能是否可以装配
在这里插入图片描述
调用我们之前编辑的让对应的可装配插槽高亮效果
在这里插入图片描述
我们还需要创建一个跟随拖拽的用户控件,这里,我对主动技能和被动技能做了区分,(因为它们的大小不一样),并设置显示的背景和图标
在这里插入图片描述
接下来,就是最重要的一步,通过内容创建拖拽操作,操作类我们可以进行自定义,这里直接使用的默认的,并将self作为自定义数据传输,并将创建的控件作为拖拽显示控件
在这里插入图片描述
接着,我覆写拖拽取消时,如果玩家放弃拖拽,我们需要将技能装配插槽恢复默认状态
在这里插入图片描述

在这里插入图片描述

实现拖拽事件的接收

接下来,我们需要在技能装配插槽里实现对拖拽事件的接收,对于拖拽事件的接收,有三个,发现拖拽进去,发现拖住啊离开,以及放置时
在这里插入图片描述
我们在拖动进入时,从数据中获取我们创建的对应数据
在这里插入图片描述
这里,我们对Payload转换为技能按钮,并判断当前是否能够高亮显示,判断条件就是输入标签不同,技能类型相同
在这里插入图片描述
然后就是对拖拽生成的UI上调用它的高亮函数
在这里插入图片描述
在这里插入图片描述
高亮的实现和技能装配插槽的高亮实现逻辑相同,额外增加一张图片,控制它的显示隐藏
在这里插入图片描述
如果拖拽离开此控件,我们将拖拽物体上的高亮效果取消
在这里插入图片描述
接着,我们再覆写放置时,就是玩家正确的放置了技能
在这里插入图片描述
我们在触发放置时,就和触发点击时一样,直接使用点击的事件即可
在这里插入图片描述
注意,将装配高亮效果取消掉,然后返回处理完成
在这里插入图片描述

接下来就是验证功能查缺补漏
在这里插入图片描述

处理委托的多次绑定

现在,我们关闭技能面板,然后再打开,会发现事件会被多次触发。
出现这个原因是,我们在创建控件时进行的委托绑定,但在关闭面板时,没有销毁。

解决这个问题,有两种方案,我先说第一种,就是我不会用的

我们可以在蓝图里,销毁控件是,调用取消绑定,可以指定函数取消指定回调事件,或者将所有委托全部取消掉,这种在蓝图实现起来有点乱。
在这里插入图片描述

接着就是介绍第二种方式,那就是实现一个函数,供蓝图调用,在控件销毁时,调用即可

我们在控制器基类里增加一个函数,用于清除委托绑定

	UFUNCTION(BlueprintCallable)virtual void ClearAllDelegate();  //清除全部委托绑定

并将在基类里绑定的委托清除掉

void URPGWidgetController::ClearAllDelegate()
{AbilityInfoDelegate.Clear();
}

在派生类里,我们首先覆写函数,

virtual void ClearAllDelegate() override;

然后在实现里,首先调用父类函数执行清除,接着实现在派生类里的委托变量的清除

void UAttributeMenuWidgetController::ClearAllDelegate()
{Super::ClearAllDelegate();AttributeInfoDelegate.Clear();AttributePointsChangedDelegate.Clear();
}

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

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

相关文章

杰发科技AC7840——CAN通信简介(8)_通过波特率和时钟计算SEG_1/SEG_2/SJW/PRESC

通过公式计算 * 波特率和采样点计算公式:* tSeg1 (S_SEG_1 2); tSeg2 (S_SEG_2 1).* BandRate (SCR_CLK / (S_PRESC 1) / ((S_SEG_1 2) (S_SEG_2 1))), SCR_CLK 为CAN 模块源时钟* SamplePoint (tSeg1 / (tSeg1 tSeg2)). {0x0D, 0x04, 0x04, 0x3B},…

文件IO和多路复用IO

目录 前言 一、文件 I/O 1.基本文件 I/O 操作 1.1打开文件 1.2读取文件内容 (read) 1.3写入文件 (write) 1.4关闭文件 (close) 2.文件指针 二、多路复用 I/O 1.常用的多路复用 I/O 模型 1.1select 1.2poll 1.3epoll 2.使用 select、poll 和 epoll 进行简单的 I/O…

软件测试最全面试题,了解一下

一、前言 近期有不少同学,朋友问我什么是软件测试,它是干什么的,我适不适合做、这行发展前景、工资怎么样等等等…在这里我把问题总结一下,整理一篇文章出来。 我也看过很多贴吧、论坛,在入行之前对这块都是迷茫的&a…

数据结构----栈

一丶概念 只能在一端进行插入和删除操作的线性表(又称为堆栈),进行插入和删除操作的一端称为栈顶,另一端称为栈底 二丶特点 先进后出 FILO first in last out 后进先出 LIFO last in first out 三丶顺序栈 逻辑结构&…

Nginx: 配置项之http模块connection和request的用法以及limit_conn和limit_req模块

connection和request connection 就是一个连接, TCP连接 客户端和服务器想要进行通信的话,有很多种方式比如说, TCP的形式或者是UDP形式的通常很多应用都是建立在这个TCP之上的所以, 客户端和服务器通信,使用了TCP协议的话,必然涉及建立TCP连…

Java JNA调用C函数常见问题及解决方法

目录 1 undefined symbol:xxx2 Java映射C数组乱码3 Java使用String接收不到C函数返回的char*4 Unable to load DLL xxx.dll5 java.lang.UnsatisfiedLinkError: %1 不是有效的 Win32 应用程序6 无效的ELF头7 Structure array elements must use contiguous memory8 j…

msvcp120.dll丢失是怎么回事?几种靠谱修复msvcp120.dll的方法

在使用基于Windows的计算机进行日常工作或娱乐时,您可能会遇到一个错误消息:“无法启动此程序,因为计算机中丢失msvcp120.dll。”这样的提示通常在尝试启动某些程序或游戏时弹出,导致应用无法正常运行。这个问题通常与系统中的某个…

CSS3页面布局-三栏-固定宽度布局

布局的基本概念 多栏布局三种基本实现方案:固定宽度,流动,弹性。 固定宽度布局:大小不会随用户调整浏览器窗口大小。 一版960-1100,960常见,可以被3,4,5,6,8,10,12,16整除。 流动布局:大小会随用户调整…

数据结构——链式二叉树的实现与分治编程思维(c语言实现)

目录 前言: 1.前置说明 2.链式二叉树的遍历 2.1 前序,中序及后续遍历 2.2 前序遍历实现 2.3 中序遍历实现 2.4 后续遍历实现 3.结点个数以及高度等 3.1 结点个数 3.2 结点高度 3.3 叶子结点的个数 前言: 在之前的学习中&…

【图解秒杀系列】秒杀技术点——多级缓存、分层过滤

【图解秒杀系列】秒杀技术点——多级缓存、分层过滤 多级缓存本地缓存分布式缓存 分层过滤 多级缓存 多级缓存在秒杀系统中是非常重要的一个技术点,是应对秒杀场景瞬时高并发读请求的一种有效手段。通过在数据库前面加入多个缓存层,达到过滤掉大多数读请…

优惠券秒杀项目

一、添加优惠券的同时,将优惠券信息,以及用户列表放到redis中 Override Transactional public void addSeckillVoucher(Voucher voucher) {// 保存优惠券save(voucher);// 保存秒杀信息SeckillVoucher seckillVoucher new SeckillVoucher();seckillVou…

easyexcel--多sheet页导入导出

多sheet页导出 核心代码就是下图里面的,使用EasyExcel.writeSheet创建一个sheet,然后用excelWriter写入就行了,很简单 GetMapping("downloadMultiSheet")public void downloadMultiSheet(HttpServletResponse response) throws IOException {…

【Qt】输入类控件QDateTimeEdit

目录 输入类控件QDateTimeEdit 例子:实现日期计算器 输入类控件QDateTimeEdit QDate Edit作为日期的微调框 QTime Edit作为时间的微调框 QDateTimeEdit作为时间日期的微调框 下面主要讲解QDateTimeEdit: 核心属性 属性说明 dateTime 时间⽇期的值.…

【Hot100】LeetCode—101. 对称二叉树

目录 1- 思路借助队列 2- 实现⭐101. 对称二叉树——题解思路 3- ACM 实现 原题连接&#xff1a;101. 对称二叉树 1- 思路 借助队列 1- 创建队列&#xff1a;Queue<TreeNode> queue&#xff0c;初始化加入 root.left 和 root.right2- 判断逻辑&#xff1a;while(!queu…

软件开发者的首选:最佳Bug测试工具Top 10

本篇文章介绍了以下软件bug测试管理工具&#xff1a;PingCode、Worktile、Test360、禅道、码云Gitee、优云测试、Jira、GitHub、Axosoft、Bugzilla。 在开发过程中&#xff0c;Bug的管理往往是最让人头疼的问题之一。小问题积累起来不仅会拖延项目进度&#xff0c;还可能影响到…

如何优雅处理异步组件加载:Vue 3 的 Suspense 特性

在日常开发中&#xff0c;我们可能会遇到网络不佳或内容加载时间较长的情况。如果当前页面没有任何内容提示&#xff0c;用户的体验非常糟糕&#xff0c;可能会反复刷新以便加载成功。因此&#xff0c;我们需要给用户提供一个加载中的效果&#xff0c;告知用户“我在努力加载中…

基于单片机的人体健康监测系统的设计

本设计以STM32F103C8T6单片机作为主控&#xff0c;通过MAX30102采集心率、血氧值&#xff0c;通过MSP20血压采集模块检测血压值&#xff0c;通过MLX90614红外体温采集模块检测体温值。OLED屏可以显示以上检测的信息&#xff0c;并可以通过蓝牙模块将信息发送给手机APP。当检测值…

利用VirtualBox安装CentOS系统

博主这次用VirtualBox虚拟机安装CentOS系统。无论是大小型项目都是要发布到云主机上面&#xff0c;必然要用到Linux系统&#xff0c;有的人的本地电脑硬件配置不高&#xff0c;没有办法运行数据库集群&#xff0c;所以只能借助云主机。毕竟云主机也是Linux系统&#xff0c;大家…

大数据-92 Spark 集群 SparkRDD 原理 Standalone详解 ShuffleV1V2详解 RDD编程优化

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff08;已更完&#xff09;HDFS&#xff08;已更完&#xff09;MapReduce&#xff08;已更完&am…

OZON什么产品好卖丨OZON婴儿用具产品

Top1 摇铃 Деревянная стойка тренажер Монтессори для мобилей и игрушек для новорожденных / развивающая дуга 商品id&#xff1a;1557614414 月销量&#xff1a;707 OZON婴儿用具…