Unity3D UI 拖拽
Unity3D 实现 UI 元素拖拽功能。
UI 拖拽
通常画布上的 UI 元素都是固定位置的,我们可以通过实现拖拽接口,让 UI 元素可以被拖拽到其他位置。
拖拽接口
创建一个脚本 UIDrag.cs
,在默认继承的 MonoBehaviour
后面,再继承三个接口。
IBeginDragHandler
(开始拖拽)IDragHandler
(拖拽中)IEndDragHandler
(结束拖拽)
继承接口之后,要在脚本中实现接口中定义的方法,即 OnBeginDrag
、OnDrag
、OnEndDrag
。
using UnityEngine;
using UnityEngine.EventSystems;public class UIDrag : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
{public void OnBeginDrag(PointerEventData eventData){}public void OnDrag(PointerEventData eventData){transform.position = eventData.position;}public void OnEndDrag(PointerEventData eventData){}
}
这里先在 OnDrag
方法中,把 eventData.position
赋值给 transform.position
。
然后创建一个 Image,把 UIDrag
脚本拖拽到 Image 上。
运行游戏,点击拖拽图片。
画布渲染模式
上述的拖拽实现,是基于画布的 Overlay 模式。
如果把画布渲染模式改成 Camera 模式,上述的代码实现就会出现问题。
因为 Camera 模式的画布会被缩小到相机的视野范围内,坐标的数值会变得很小。
此时的运行效果,拖拽后图片飞到了离画布很远的位置,坐标错误。
所以我们需要对拖拽时获得的坐标位置进行转换。
坐标转换
首先,定义一个 RectTransform
变量,在 Awake
时进行赋值。
然后利用 RectTransformUtility.ScreenPointToWorldPointInRectangle
方法,把自身的 rect
、eventData.position
、eventData.pressEventCamera
传入,如果坐标转换正常,则会返回转换后的 worldPoint
,把这个坐标赋值给 rect.position
就可以了。
这个方法可以把屏幕空间坐标转换成 UI 元素所在的世界坐标。
using UnityEngine;
using UnityEngine.EventSystems;public class UIDrag : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
{RectTransform rect;void Awake(){rect = GetComponent<RectTransform>();}public void OnBeginDrag(PointerEventData eventData){}public void OnDrag(PointerEventData eventData){if (RectTransformUtility.ScreenPointToWorldPointInRectangle(rect, eventData.position,eventData.pressEventCamera, out Vector3 worldPoint)){rect.position = worldPoint;}}public void OnEndDrag(PointerEventData eventData){}
}
修改代码后,无论画布是 Overlay 还是 Camera 模式,都可以正常拖拽。
开始与结束拖拽
单纯的拖拽,只需要 OnDrag
方法,而 OnBeginDrag
和 OnEndDrag
可以为拖拽操作添加更多的逻辑处理。
例如,在场景中添加两个 Image,修改名字,改变颜色和不透明度,放置到左右两边。
然后在代码中添加更多的逻辑,添加一个 raycastResults
用于保存射线检测到的 UI 元素列表,通过 EventSystem.current.RaycastAll
方法,把鼠标经过的 UI 元素都添加到列表中(包含 Image 自己)。
如果鼠标经过的 UI 元素的名字包含 Container,就把目标元素赋值给 target
;如果列表中只有 Image 自己,则 target
为空。
我们可以在 OnBeginDrag
中,把 Image 原来的位置保存起来。在 OnEndDrag
中,检查 target
为空时,把原来的位置赋值给 Image,回到原位。只有在 target
不为空时,Image 才会移动到目标容器位置。
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;public class UIDrag : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
{RectTransform rect;List<RaycastResult> raycastResults;GameObject target;Vector3 originPos;void Awake(){rect = GetComponent<RectTransform>();raycastResults = new List<RaycastResult>();}public void OnBeginDrag(PointerEventData eventData){originPos = transform.position;}public void OnDrag(PointerEventData eventData){if (RectTransformUtility.ScreenPointToWorldPointInRectangle(rect, eventData.position,eventData.pressEventCamera, out Vector3 worldPoint)){rect.position = worldPoint;}// 清空上一次的射线检测结果raycastResults.Clear();// 进行射线检测EventSystem.current.RaycastAll(eventData, raycastResults);// 包含两个 UI 元素以上if (raycastResults.Count > 1){// 遍历检测结果foreach (RaycastResult result in raycastResults){// 跳过自身对象的检测if (result.gameObject == gameObject) continue;// 检测到目标容器if (result.gameObject.name.Contains("Container")){target = result.gameObject;}}}// 只包含自己,没有目标else{target = null;}}public void OnEndDrag(PointerEventData eventData){if (target == null){transform.position = originPos;}else{transform.position = target.transform.position;}}
}
运行效果:
相关文章:

Unity3D UI 拖拽
Unity3D 实现 UI 元素拖拽功能。 UI 拖拽 通常画布上的 UI 元素都是固定位置的,我们可以通过实现拖拽接口,让 UI 元素可以被拖拽到其他位置。 拖拽接口 创建一个脚本 UIDrag.cs,在默认继承的 MonoBehaviour 后面,再继承三个接…...
介绍一下memcpy(c基础)
memcpy函数void *memcpy(void *dest, const void *src, size_t n); dest:指向目标内存区域的指针,即复制的目的地。src:指向源内存区域的指针,即要被复制的内容的来源。n:要复制的字节数 主要功能是将src所指向的内存…...

【网络面试篇】HTTP(2)(笔记)——http、https、http1.1、http2.0
目录 一、相关面试题 1. HTTP 与 HTTPS 有哪些区别? 2. HTTPS 的工作原理?(https 是怎么建立连接的) (1)ClientHello (2)SeverHello (3)客户端回应 &a…...
python-23-一篇文章帮你理解Python推导式
python-23-一篇文章帮你理解Python推导式 一.简介 在 Python 中,推导式(Comprehensions)是一个简洁的语法,用于通过某种可迭代对象快速生成新的对象(如列表、字典、集合等!来开始我们今天的日拱一卒&…...

WPF中如何简单的使用CommunityToolkit.Mvvm创建一个项目并进行 增删改查
目录 开始前准备的数据库dbblog如下: 第一步:创建项目后下载四个NuGet程序包 第二步:删除原本的MainWindow.XAML文件 并创建如下的目录结构 然后在View文件夹下面创建Login.XAML和Main.XAML 并且在App.XAML中将启动项改为Login.X…...
CesiumJS 案例 P15:检测标记、鼠标点击移动标记、鼠标拖动标记
CesiumJS CesiumJS API:https://cesium.com/learn/cesiumjs/ref-doc/index.html CesiumJS 是一个开源的 JavaScript 库,它用于在网页中创建和控制 3D 地球仪(地图) 一、检测标记 <!DOCTYPE html> <html lang"en&…...

Webserver(4.9)本地套接字的通信
目录 本地套接字 本地套接字 TCP\UDP实现不同主机、网络通信 本地套接字实现本地的进程间的通信,类似的,一般采用TCP的通信流程 生成套接字文件 #include<arpa/inet.h> #include<stdio.h> #include<stdlib.h> #include<unistd.h&…...

[IAA系列] Image Aesthetic Assessment
Preface 本文旨在记录个人结合AI工具对IAA这个领域的一些了解,主要是通过论文阅读的方式加深对领域的了解。有什么问题,欢迎在评论区提出并讨论。 什么是IAA Image Aesthetic Assessment(图像美学评估)是一种评估图像在视觉上的…...

基于springboot的高校科研管理系统(源码+调试+LW)
项目描述 临近学期结束,还是毕业设计,你还在做java程序网络编程,期末作业,老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。这里根据你想解决的问题,今天给…...

Flutter环境配置
配置环境变量 PUB_HOSTED_URLhttps://pub.flutter-io.cn FLUTTER_STORAGE_BASE_URLhttps://storage.flutter-io.cn 这个命令是用来配置 Flutter 的镜像源地址,主要是为了解决在中国大陆地区访问 Flutter 官方资源较慢的问题 具体的操作做如下: 右键点击"此…...

Rip动态路由及Rip动态路由优化
动态路由Rip Tip:Rip动态路由实现多个路由间不同网段通信。 本次实验目的,通过给ar1,ar2,ar3配置rip动态路由,实现pc1 ping通 pc2。 AR1配置如下: <Huawei>sy Enter system view, return user view with CtrlZ. [Huawei]…...
双路快速排序和三路排序算法
双路快速排序 一、概念及其介绍 双路快速排序算法是随机化快速排序的改进版本,partition 过程使用两个索引值(i、j)用来遍历数组,将 <v 的元素放在索引i所指向位置的左边,而将 >v 的元素放在索引j所指向位置的…...
SQL server增删改查语句和实例
在 SQL Server 中,增删改查操作分别对应 INSERT、DELETE、UPDATE 和 SELECT 语句。以下是具体介绍及实例: 一、插入数据(INSERT) 语法: INSERT INTO table_name (column1, column2, column3,...) VALUES (value1, val…...

强化学习_06_pytorch-PPO2实践(ALE/Breakout-v5)
一、环境适当调整 数据收集:RecordEpisodeStatistics进行起始跳过n帧:baseSkipFrame一条生命结束记录为done:EpisodicLifeEnv得分处理成0或1:ClipRewardEnv叠帧: FrameStack 图像环境的基本操作,方便CNN捕捉智能体的行动 向量空间reset处理修…...

《JVM第8课》垃圾回收算法
文章目录 1.标记算法1.1 引用计数法1.2 可达性分析法 2.回收算法2.1 标记-清除算法(Mark-Sweep)2.2 复制算法(Coping)2.3 标记-整理算法(Mark-Compact) 3.三种垃圾回收算法的对比 为什么要进行垃圾回收&…...
SpringBoot整合Freemarker(二)
if分支 语法: <#if condition>... <#elseif condition2>... <#elseif condition3>... <#else>... </#if> 例子: <#if x 1>x is 1 </#if> --------------------------------- <#if x 1>x is 1 <…...

element plus el-form自定义验证输入框为纯数字函数
element plus 的el-form 使用自定义验证器,验证纯数字,禁止输入小数、中文、字母、特殊符号。input的maxlength为最大输入多少位长度 效果图 <el-form ref"dataFormRef" :model"dataForm" :rules"dataRules" label-w…...

Android笔记(三十一):Deeplink失效问题
背景 通过deeplink启动应用之后,没关闭应用的情况下,再次使用deeplink会失效的问题,是系统bug导致的。此bug仅在某些设备(Nexus 5X)上重现,launchMode并且仅当应用程序最初通过深层链接启动并再次通过深层…...

图神经网络初步实验
实验复现来源 https://zhuanlan.zhihu.com/p/603486955 该文章主要解决问题: 1.加深对图神经网络数据集的理解 2.加深对图神经网络模型中喂数据中维度变化的理解 原理问题在另一篇文章分析: 介绍数据集:cora数据集 其中的主要内容表示为…...

创建线程时传递参数给线程
在C中,可以使用 std::thread 来创建和管理线程,同时可以通过几种方式将参数传递给线程函数。这些方法包括使用值传递、引用传递和指针传递。下面将对这些方法进行详细讲解并给出相应的代码示例。 1. 值传递参数 当你创建线程并希望传递参数时ÿ…...
ES6从入门到精通:前言
ES6简介 ES6(ECMAScript 2015)是JavaScript语言的重大更新,引入了许多新特性,包括语法糖、新数据类型、模块化支持等,显著提升了开发效率和代码可维护性。 核心知识点概览 变量声明 let 和 const 取代 var…...
java_网络服务相关_gateway_nacos_feign区别联系
1. spring-cloud-starter-gateway 作用:作为微服务架构的网关,统一入口,处理所有外部请求。 核心能力: 路由转发(基于路径、服务名等)过滤器(鉴权、限流、日志、Header 处理)支持负…...

【JavaWeb】Docker项目部署
引言 之前学习了Linux操作系统的常见命令,在Linux上安装软件,以及如何在Linux上部署一个单体项目,大多数同学都会有相同的感受,那就是麻烦。 核心体现在三点: 命令太多了,记不住 软件安装包名字复杂&…...

Java面试专项一-准备篇
一、企业简历筛选规则 一般企业的简历筛选流程:首先由HR先筛选一部分简历后,在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如:Boss直聘(招聘方平台) 直接按照条件进行筛选 例如:…...

Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)
参考官方文档:https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java(供 Kotlin 使用) 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...
Pinocchio 库详解及其在足式机器人上的应用
Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库,专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性,并提供了一个通用的框架&…...
Java编程之桥接模式
定义 桥接模式(Bridge Pattern)属于结构型设计模式,它的核心意图是将抽象部分与实现部分分离,使它们可以独立地变化。这种模式通过组合关系来替代继承关系,从而降低了抽象和实现这两个可变维度之间的耦合度。 用例子…...
作为测试我们应该关注redis哪些方面
1、功能测试 数据结构操作:验证字符串、列表、哈希、集合和有序的基本操作是否正确 持久化:测试aof和aof持久化机制,确保数据在开启后正确恢复。 事务:检查事务的原子性和回滚机制。 发布订阅:确保消息正确传递。 2、性…...
WebRTC从入门到实践 - 零基础教程
WebRTC从入门到实践 - 零基础教程 目录 WebRTC简介 基础概念 工作原理 开发环境搭建 基础实践 三个实战案例 常见问题解答 1. WebRTC简介 1.1 什么是WebRTC? WebRTC(Web Real-Time Communication)是一个支持网页浏览器进行实时语音…...

【Linux手册】探秘系统世界:从用户交互到硬件底层的全链路工作之旅
目录 前言 操作系统与驱动程序 是什么,为什么 怎么做 system call 用户操作接口 总结 前言 日常生活中,我们在使用电子设备时,我们所输入执行的每一条指令最终大多都会作用到硬件上,比如下载一款软件最终会下载到硬盘上&am…...