UGUI 实现拖拽功能

版权声明:快乐源于分享,转载请附链接,,, https://blog.csdn.net/Czhenya/article/details/82818881

Unity 使用UGUI 实现图片的拖拽功能

先说下思路:开始点击 --> 跟随鼠标 --> 抬起鼠标(释放点击) ===》 这个一系列的操作之后,我们希望我们的图片也是跟着在动的,,,所以这就需要几个Unity 带个几个接口,,我这之前发布的长按和点击的同步文章也说过,这里就不在赘述,需要的同学可以到官网查看,或者看我之前发布的博文。链接:https://blog.csdn.net/Czhenya/article/details/82762637

在这个功能中我用的了这几个接口的方法:

  • PointerEnterHandler - OnPointerEnter - 指针进入事件
  • IBeginDragHandler - OnBeginDrag - 开始拖拽事件
  • IDragHandler - OnDrag - 拖拽中事件
  • IEndDragHandler - OnEndDrag - 拖拽结束(被拖拽的物体调用)

有了这几个事件后,还有一个Canvas Group组件,这个组件可以通过

 this.GetComponent<CanvasGroup>().blocksRaycasts = false;//设置射线穿透

帮助你判断鼠标点击的是哪个物体,鼠标拖拽结束时碰到了那个物体,,,(PS:记得所有需要通过拖拽更换位置的都要添加这个组件) 如下图:
1

示例简述:
在这里插入图片描述

上面的1-6是我要移动的图片,,,就像我们手机上的图标换位置一样,(例1:点击5开始,到2结束 ,那么2-4的图标都向后移动一位,,5占据2的位置。例2:点击1开始,到4结束,那么2-4的图标都先前移动一位,1占据4的位置。诸如此类)

下面是我项目中解决这个问题的部分代码:
(PS:大家只看实现接口这几个方法就可以了,,,具体的逻辑还需要根据自己的项目需求实现)

using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using System.Collections.Generic;
using DG.Tweening;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

[RequireComponent(typeof(RectTransform))]
////给控件添加监听事件要实现的一些接口
public class LobbyIconDrag : MonoBehaviour, IBeginDragHandler, IDragHandler, IDropHandler, IEndDragHandler, IPointerDownHandler
{

    private Dictionary<int, Vector3> IconPosDict = new Dictionary<int, Vector3>();

    public Dictionary<int, string> IconObjDict = new Dictionary<int, string>();
    
    private string startName = "";  //从start开始 到 endName
    private string endName = "";

    private Vector3 BeforePos;

    void Start()
   {

        //不变的位置字典...
        IconPosDict.Add(1, new Vector3(-112, 105));
        IconPosDict.Add(2, new Vector3(124, 105));
        IconPosDict.Add(3, new Vector3(369, 105));
        IconPosDict.Add(4, new Vector3(-112, -133));
        IconPosDict.Add(5, new Vector3(124, -133));
        IconPosDict.Add(6, new Vector3(369, -133));

        //测试用的初始化...
        IconObjDict.Add(1, "C#");
        IconObjDict.Add(2, "Java");
        IconObjDict.Add(3, "Lua");
        IconObjDict.Add(4, "Unity");
        IconObjDict.Add(5, "DW");
        IconObjDict.Add(6, "PS");
       
    }
	//指针进入是调用 --> 用于记住开始点击的图片是谁,以及他现在的位置
    public void OnPointerDown(PointerEventData EventData)
    {
        //Debug.Log("1 ... " + EventData.pointerEnter.name);
        startName = EventData.pointerEnter.name;
        for (int i = 0; i < IconObjDict.Count; i++)
        {
            if (EventData.pointerEnter.name == IconObjDict[i + 1])
            {
                BeforePos = IconPosDict[i + 1];
            }
        }
    }

    /// <summary>
    /// 开始拖动
    /// </summary>
    /// <param name="EventData"></param>
    public void OnBeginDrag(PointerEventData EventData)
    {
        this.GetComponent<CanvasGroup>().blocksRaycasts = false;//设置射线穿透
    }

    /// <summary>
    /// 正在拖拽
    /// </summary>
    /// <param name="EventData"></param>
    public void OnDrag(PointerEventData EventData)
    {
        this.transform.position = Input.mousePosition;  //跟随鼠标的位置...
        if (Mathf.Abs(Input.mousePosition.x) >= 600 || Mathf.Abs(Input.mousePosition.x) >= 300 )
        {
            //超出界限 就回到以前的位置...
            this.transform.localPosition = BeforePos;
        }
    }

    /// <summary>
    /// 拖拽结束(被拖拽的物体调用)
    /// </summary>
    /// <param name="eventData"></param>
    public void OnEndDrag(PointerEventData EventData)
    {
        endName = EventData.pointerEnter.name;  //记录结束位置的图片名称,方便后面更改位置的逻辑操作
        this.GetComponent<CanvasGroup>().blocksRaycasts = true;//设置射线穿透
        // Debug.Log("3 ... " + EventData.pointerEnter.name);
        ChangePos();  //调用图片移动的逻辑
    }

    /// <summary>
    /// 拖拽结束(拖拽结束后的位置(即鼠标位置)如果有物体,则那个物体调用)
    /// </summary>
    /// <param name="EventData"></param>
    public void OnDrop(PointerEventData EventData)
    {
        //很难用...      
    }

    /// <summary>
    /// 移动图标位置逻辑
    /// </summary>
    private void ChangePos()
    {
        int start = -1;
        int end = -1;

        for (int i = 0; i < IconObjDict.Count; i++)
        {
            if (startName == IconObjDict[i + 1])
            {
                start = i + 1;
            }
            if (endName == IconObjDict[i + 1])
            {
                end = i + 1;
            }
        }
       // Debug.Log("start :" + start + " ... endNun:" + end);
        if (start != -1 && end != -1)  //判断是否发生移动...
        {        
			
            //小 --> 大  (如: 1->6) 从Start后一位(2) 开始依次向前一位,直到 6 -> 5 结束 (2-1,3-2,4-3,5-4,6-5, 1-6)   
            if (start < end)
            {
                string tempName = IconObjDict[start];

                for (int i = start; i < end; i++)
                {
                    IconObjDict[i] = IconObjDict[i + 1];
                }
                IconObjDict[end] = tempName;

            }
            //大 --> 小  (如: 6->1) 从End(1) 开始依次向后一位,直到 Start(6) 结束 (1-2,2-3,3-4,4-5,5-6,6-1)
            else if (start > end)
            {
                string tempName;
                string temp = IconObjDict[start];

                for (int i = start; i > end; i--)
                {
                    IconObjDict[i] = IconObjDict[i - 1];
                }
                IconObjDict[end] = temp;
            }
            //else { 开始和结束一样,没有移动不做处理;  }
          
            for (int i = 0; i < IconObjDict.Count; i++)
            {
                Debug.Log("查看是否转换对了..." + IconObjDict[i + 1]);
            }
        }
        else
        {
           Debug.Log("图标位置乱了...");
        }
        ReadIconPos();
    }

    /// <summary>
    /// 对图标进行排列
    /// </summary>
    public void ReadIconPos()
    {
        isChangePos = true;

        for (int i = 0; i < IconObjDict.Count; i++)
        {
            //DOTween.To(() => this.transform.GetChild(i).localPosition, r => this.transform.GetChild(i).localPosition = r, IconPosDict[i + 1], 0.2f);

            GameObject go = FindPos(IconObjDict[i + 1]);
            if (go != null)
            {
                DOTween.To(() => go.transform.localPosition, r => go.transform.localPosition = r, IconPosDict[i + 1], 0.2f);
            }
            //Debug.Log("排序后位置: " + LobbyIconDrag.Instance.IconObjDict[i + 1] + "... " + IconPosDict[i + 1]);
        }  
    }


    /// <summary>
    ///  根据传入字符串,找到对应的图标
    /// </summary>
    /// <param name="str">图标名称</param>
    /// <returns>图标对象</returns>
    GameObject FindPos(string str)
    {
        GameObject go;
        for (int i = 0; i < transform.parent.childCount; i++)
        {
            if (this.transform.parent.GetChild(i).name == str)
            {
                go = this.transform.parent.GetChild(i).gameObject;
                return go;
            }
        }
        return null;
    }


    //Vector3 imgReduceScale = new Vector3(0.8f, 0.8f, 1);   //设置图片缩放
    //Vector3 imgNormalScale = new Vector3(1, 1, 1);   //正常大小

    ////当鼠标进入图片时调用   对应接口   IPointerEnterHandler
    //public void OnPointerEnter(PointerEventData eventData)
    //{
    //    this.transform.localScale = imgReduceScale;   //缩小图片
    //}

    ////当鼠标退出图片时调用   对应接口   IPointerExitHandler
    //public void OnPointerExit(PointerEventData eventData)
    //{
    //    this.transform.localScale = imgNormalScale;   //回复图片
    //}
}

猜你喜欢

转载自blog.csdn.net/Czhenya/article/details/82818881