unity中 使用IDragHandler拖动交换子物体

文章描述了一个名为SwapPanel的Unity脚本,它实现了拖动事件处理,用于在UI中的RectTransform对象间交换位置。使用了DG.Tweening库进行平滑动画效果。
摘要由CSDN通过智能技术生成

using DG.Tweening;
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using VRSightCheck.Scripts;

public class SwapPanel : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
{
    /// <summary>
    /// 是否已经响应拖拽
    /// </summary>
    public static bool isDrag = false;

    private List<RectTransform> items;  // 子物体数组

    private int currentIndex = -1;  // 当前需要交换位置的子物体索引

    /// <summary>
    /// 开始点击gameobject
    /// </summary>
    private GameObject mStartGo;

    /// <summary>
    /// 开始坐标
    /// </summary>
    private Vector3 startPos = Vector3.zero;

    /// <summary>
    /// 结束点击gameobject
    /// </summary>
    private GameObject mEndGo;

    /// <summary>
    /// 结束坐标
    /// </summary>
    private Vector3 endPos = Vector3.zero;

    /// <summary>
    /// 是否正在移动
    /// </summary>
    private bool isMove = false;

    /// <summary>
    /// 移动时间
    /// </summary>
    private const float MOVE_TIME = 0.2f;

    /// <summary>
    /// 动画
    /// </summary>
    private Tweener[] tws;

    /// <summary>
    /// 成功换位置事件
    /// </summary>
    private Action<GameObject, GameObject> ChangeSucAct;

    private void Awake()
    {
        items = new List<RectTransform>();
        currentIndex = -1;
        mStartGo = null;
        startPos = Vector3.zero;
        mEndGo = null;
        endPos = Vector3.zero;
        isMove = false;
        tws = new Tweener[3];
        ChangeSucAct = new Action<GameObject, GameObject>(ChangeSuc);
    }

    /// <summary>
    /// 清除子物体
    /// </summary>
    public void ClearItem()
    {
        items.Clear();
    }

    /// <summary>
    /// 添加子物体
    /// </summary>
    public void AddItem(RectTransform it)
    {
        items.Add(it);
    }

    /// <summary>
    /// 设置委托
    /// </summary>
    /// <param name="act"></param>
    public void SetChangeSucAct(Action<GameObject, GameObject> act)
    {
        ChangeSucAct = act;
    }

    public void OnBeginDrag(PointerEventData eventData)
    {
        //Debug.Log("OnBeginDrag=======================>");
        if (items.Count == 0 || isMove || isDrag) return;
        // 检查触摸点是否在另一个子物体上,并根据索引信息交换两个子物体的位置
        List<RaycastResult> results = new List<RaycastResult>();
        EventSystem.current.RaycastAll(eventData, results);
        if (results.Count == 0) return;
        List<GameObject> gos = new List<GameObject>();
        for (int i = 0; i < results.Count; i++)
        {
            gos.Add(results[i].gameObject);
        }
        // 检查触摸点是否在其中一个子物体上
        for (int i = 0; i < items.Count; i++)
        {
            //if (RectTransformUtility.RectangleContainsScreenPoint(items[i], eventData.position, UICanvasManager.Instance.CameraCanvas))
            if(gos.Contains(items[i].gameObject))
            {
                currentIndex = i;
                mStartGo = items[i].gameObject;
                startPos = items[i].position;

                isDrag = true;
                break;
            }
        }
    }

    public void OnDrag(PointerEventData eventData)
    {
        //Debug.Log("OnDrag=======================>");
        if (items.Count == 0 || isMove) return;
        
        if (currentIndex >= 0)
        {
            // 根据触摸点的移动距离计算出当前子物体应该移动的位置
            Vector2 offset = eventData.delta / transform.localScale.x;
            if(items.Count > currentIndex)
            {
                items[currentIndex].anchoredPosition += offset;
            }
        }
    }

    public void OnEndDrag(PointerEventData eventData)
    {
        //Debug.Log("OnEndDrag=======================>");
        if (items.Count == 0 || isMove || mStartGo == null) return;
        
        for (int i = 0; i < items.Count; i++)
        {
            if (i != currentIndex && RectTransformUtility.RectangleContainsScreenPoint(items[i], eventData.position , UICanvasManager.Instance.CameraCanvas))
            {
                mEndGo = items[i].gameObject;
                endPos = items[i].position;
                Change();
                break;
            }
        }
        if (mEndGo == null)
        {
            MoveBack();
        }
        currentIndex = -1;

        isDrag = false;
    }

    /// <summary>
    /// 清除开始点击gameObject
    /// </summary>
    void ClearStartGo()
    {
        if (mStartGo == null) return;
        mStartGo.transform.localScale = Vector3.one;
        mStartGo = null;
    }


    /// <summary>
    /// 未成功换位置,返回
    /// </summary>
    void MoveBack()
    {
        isMove = true;

        tws[0] = mStartGo.transform.DOMove(startPos, MOVE_TIME);

        tws[0].SetEase(Ease.Linear);
        tws[0].OnComplete( () =>{
            ClearStartGo();
            isMove = false;
        });

        if (mEndGo != null)
        {
            mEndGo = null;
        }
    }

    /// <summary>
    /// 替换位置
    /// </summary>
    void Change()
    {
        isMove = true;
        int idx = mStartGo.transform.GetSiblingIndex();
        mStartGo.transform.SetSiblingIndex(mEndGo.transform.GetSiblingIndex());
        mEndGo.transform.SetSiblingIndex(idx);

        tws[1] = mStartGo.transform.DOMove(endPos, MOVE_TIME);
        tws[1].SetEase(Ease.Linear);
        tws[2] = mEndGo.transform.DOMove(startPos, MOVE_TIME);
        tws[2].SetEase(Ease.Linear);
        tws[2].OnComplete(() => {
            Debug.Log("替换位置================>" + ChangeSucAct);
            ChangeSucAct(mStartGo, mEndGo);
            ClearStartGo();
            isMove = false;
            mEndGo = null;
        });
    }


    private void OnDestroy()
    {
        //停止动画
        for (int i = 0; i < tws.Length; i++)
        {
            if (tws[i] != null) tws[i].Kill();
        }
    }


    private void ChangeSuc(GameObject arg1, GameObject arg2)
    {

    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值