Unity开箱即用的UGUI面板的拖拽移动功能

news/2024/7/8 10:35:26 标签: unity, 游戏引擎, ugui, 面板拖拽

文章目录

      • 👉一、背景
      • 👉二、效果图
      • 👉三、原理
      • 👉四、核心代码
      • 👉五,总结

👉一、背景

之前做PC项目时常常有面板拖拽移动的需求,今天总结封装一下,做成一个随时随地可复用的拖拽面板功能。

👉二、效果图

请添加图片描述

👉三、原理

实现原理也非常简单。首先继承UI事件系统下的两个接口:

IBeginDragHandler, IDragHandler

进而实现两个接口方法即可,主要是在开始拖拽事件里面,记录鼠标按下的坐标mMouseDownPosition和面板的初始坐标mPanelOriginPosition;然后在拖拽过程中鼠标在Canvas下的坐标,减去开始拖拽的鼠标坐标得到一个鼠标坐标偏移量,加上原始面板坐标得到一个新的拖拽位置的坐标,进行坐标赋值即可。

👉四、核心代码

using UnityEngine;
using UnityEngine.EventSystems;

namespace Utility
{
    /// <summary>
    /// UGUI面板的拖拽移动功能
    /// </summary>
    [RequireComponent(typeof(RectTransform))]
    public class DragPanel : MonoBehaviour, IBeginDragHandler, IDragHandler
    {
        /// <summary>
        /// 静态方法,提供动态绑定拖拽面板的接口
        /// </summary>
        /// <param name="rectTransform"></param>
        /// <returns></returns>
        public static DragPanel Get(RectTransform rectTransform)
        {
            DragPanel dragPanel = rectTransform.gameObject.GetComponent<DragPanel>();
            if (dragPanel == null)
            {
                dragPanel = rectTransform.gameObject.AddComponent<DragPanel>();
            }
            return dragPanel;
        }

        /// <summary>
        /// 当前拖拽面板的根节点,一般是Canvas
        /// </summary>
        private RectTransform canvasRect;
        private Canvas rootCanvas;
        private Camera uiCam;
        /// <summary>
        /// 是否允许拖拽
        /// </summary>
        private bool isAllowDrag;

        private Vector3 mMouseDownPosition;
        private Vector3 mPanelOriginPosition;

        private void Awake()
        {
            Transform root = transform.root;
            if (root != null)
            {
                rootCanvas = root.GetComponent<Canvas>();
                canvasRect = root as RectTransform;
                if (rootCanvas.renderMode == RenderMode.ScreenSpaceCamera)
                {
                    uiCam = rootCanvas.worldCamera;
                }
            }
            isAllowDrag = rootCanvas != null;
        }

        public void OnBeginDrag(PointerEventData eventData)
        {
            if (!isAllowDrag) return;
            RectTransformUtility.ScreenPointToWorldPointInRectangle(
                canvasRect,
                Input.mousePosition,
                uiCam,
                out mMouseDownPosition);
            mPanelOriginPosition = transform.position;
        }

        public void OnDrag(PointerEventData eventData)
        {
            if (!isAllowDrag) return;
            Vector3 currentMousePosInUGUI;
            RectTransformUtility.ScreenPointToWorldPointInRectangle(
                canvasRect,
                Input.mousePosition,
                uiCam,
                out currentMousePosInUGUI);
            transform.position = mPanelOriginPosition + (currentMousePosInUGUI - mMouseDownPosition);
        }
    }
}

食用方法:

  1. 直接将DragPanel脚本拖拽赋值给需要拖拽的UI面板。
    在这里插入图片描述

  2. 如果需要拖拽功能的UI面板多,可使用动态绑定方法,该脚本提供了一个Get方法,参数为需要拖拽的对象的RectTransform组件。
    代码动态绑定方法如下:

			RectTransform rectTransform = xxx;//需要赋值,对象不能为空哦。
            DragPanel.Get(rectTransform);

👉五,总结

后续可以进行优化的地方:

  • 鼠标拖拽移动可以是用平滑移动方法
  • 对拖拽范围进行限制

http://www.niftyadmin.cn/n/5537091.html

相关文章

Kubernetes的基本概念与安装

Kubernetes的基本概念与安装 Kubernetes 是一个开源的容器编排平台&#xff0c;用于自动化应用程序的部署、扩展和管理。它由 Google 设计并捐赠给了 Cloud Native Computing Foundation&#xff0c;现在已经成为云原生技术的事实标准。 1. Kubernetes 的基本概念 1.1_Pods …

【web APIs】快速上手Day05(Bom操作)

目录 Web APIs - 第5天笔记js组成window对象BOM定时器-延迟函数案例-5秒钟之后消失的广告 JS执行机制location对象案例-5秒钟之后跳转的页面 navigator对象histroy对象 本地存储&#xff08;今日重点&#xff09;localStorage&#xff08;重点&#xff09;sessionStorage&#…

【PYG】dataloader和densedataloader

DenseDataLoader 是专门用于处理稠密图数据的&#xff0c;而 DataLoader 通常用于处理稀疏图数据。两者的主要区别在于它们的输入数据格式和处理方式。DenseDataLoader 适合处理固定大小的邻接矩阵和节点特征矩阵的数据&#xff0c;而 DataLoader 更加灵活&#xff0c;可以处理…

外挂级OCR神器:免费文档解析、表格识别、手写识别、古籍识别、PDF转Word

TextIn Tools是一款免费的在线OCR工具&#xff0c;支持快速准确的文字和表格识别&#xff0c;手写、古籍识别&#xff0c;提供PDF转Markdown大模型辅助工具&#xff0c;同时支持PDF、WORD、EXCEL、JPG、PPT等各类格式文件的转化。 TextIn Tools特点 免费&#xff1a;所有产品提…

什么是 qobject_cast?

前言 在 C++ 中,类型转换是一项常见的操作,比如将 int 转换为 char 或将 QString 用于 QMessageBox。但是,为什么我们需要将一个类转换为另一个类呢?本文将解释 qobject_cast 是什么,它的作用以及为什么需要类型转换。 dynamic_cast 和 qobject_cast 的概述 什么是 dyn…

如何设计一个峰值电流可以100A的PCB?

目录 01.PCB上走线 那我们要选什么样的可以通过100A呢&#xff1f; 02.接线柱 03.定做铜排 04.特殊工艺 通常的PCB设计电流都不会超过10 A&#xff0c;甚至5 A。尤其是在家用、消费级电子中&#xff0c;通常PCB上持续的工作电流不会超过2 A。但是最近要给公司的产品设计动…

程序员,去哪个城市工作更幸福?

深漂、沪漂、京漂、杭漂……又是一年毕业季&#xff0c;作为CS专业or新手程序员会选择什么城市工作呢&#xff1f;希望这篇文章给各位一些参考。 根据拉勾招聘大数据研究院的数据显示&#xff0c;超六成程序员集中在一线城市&#xff0c;其中北京19%&#xff0c;深圳16%&#x…

element ui 的 el-date-picker 日期选择组件设置可选日期范围

有时候&#xff0c;在使用日历控件的时候&#xff0c;我们需要进行定制&#xff0c;控制用户只能在指定日期范围内进行日期选择&#xff0c;在这里&#xff0c;我使用了 element ui 的 el-date-picker 日期选择控件&#xff0c;控制只能选择当前月及往前的2个月&#xff0c;效果…