基于Unity中UGUI的EventTrigger组件实现的UI拖拽以及位置交换功能

本文介绍了一个Unity脚本,用于实现UI元素的拖拽功能,并在拖动过程中与其他UI位置进行交换。通过使用Dictionary和List来跟踪和管理UI元素,确保了拖拽操作的平滑性和准确性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在这里插入图片描述
如图所示,点击UI跟随鼠标移动并在拖动过程移动其他UI的位置`

public class Test : MonoBehaviour
{
    /// <summary>
    /// 记录一下当前拖拽的物体
    /// </summary>
    public Slot curSlot;
    public List<Slot> slotList = new List<Slot>();
    private Dictionary<GameObject, Slot> SlotDict = new Dictionary<GameObject, Slot>();
    private void Start()
    {
        InitSlotList();
    }
    /// <summary>
    /// 初始化槽子,记录数据以及添加事件
    /// </summary>
    private void InitSlotList()
    {
        foreach (Transform item in transform)
        {
            Slot slot = new Slot();
            slot.transform = item;
            slot.position = item.position;
            slot.content = item.GetChild(0).gameObject;
            EventTrigger trigger = slot.content.GetComponent<EventTrigger>();
            AddDragEvent(trigger);

            SlotDict.Add(item.gameObject, slot);
            slotList.Add(slot);
        }
    }

    private Vector2 lastPos;
    private Vector2 lastMousePos;
    private void OnBeginDrag(GameObject o)
    {
        curSlot = SlotDict[o.transform.parent.gameObject];
        curSlot.content = null;
        o.transform.parent = transform;

        lastPos = o.GetComponent<RectTransform>().anchoredPosition;
        lastMousePos = Input.mousePosition;
    }
    private void OnDrag(GameObject o)
    {
        Vector2 curMousePos = Input.mousePosition;
        float x = curMousePos.x - lastMousePos.x;
        float y = curMousePos.y - lastMousePos.y;
        Vector2 curPos = new Vector2(lastPos.x, lastPos.y + y);
        o.GetComponent<RectTransform>().anchoredPosition = curPos;

        lastPos = curPos;
        lastMousePos = curMousePos;
        FindNearPos(o.transform.position);
    }
    private void OnEndDrag(GameObject o)
    {
        SaveContent(curSlot, o.transform);
        curSlot = null;
    }

    private void FindNearPos(Vector2 pos)
    {
        foreach (var item in SlotDict.Values)
        {
            if (item.content!=null)
            {
                float dis = Mathf.Abs(pos.y - item.position.y);
                if (dis<50)
                {
                    //把最近slot的content放在curSlot中
                    //把当前的slot置空
                    Transform tmp = item.content.transform;
                    item.content = null;
                    SaveContent(curSlot, tmp);
                    curSlot = item;
                    break;
                }
            }
        }
    }
    private void SaveContent(Slot slot,Transform content)
    {
        content.SetParent(slot.transform);
        content.GetComponent<RectTransform>().anchoredPosition = Vector2.zero;
        slot.content = content.gameObject;
    }

    private void AddDragEvent(EventTrigger e)
    {
        EventTrigger.Entry BeginDrag = new EventTrigger.Entry();
        BeginDrag.eventID = EventTriggerType.BeginDrag;
        BeginDrag.callback.AddListener((s) =>
        {
            OnBeginDrag(e.gameObject);
        });
        EventTrigger.Entry Drag = new EventTrigger.Entry();
        Drag.eventID = EventTriggerType.Drag;
        Drag.callback.AddListener((s) =>
        {
            OnDrag(e.gameObject);
        });
        EventTrigger.Entry EndDrag = new EventTrigger.Entry();
        EndDrag.eventID = EventTriggerType.EndDrag;
        EndDrag.callback.AddListener((s) =>
        {
            OnEndDrag(e.gameObject);
        });
        e.triggers.Add(BeginDrag);
        e.triggers.Add(Drag);
        e.triggers.Add(EndDrag);
    }
}

/// <summary>
/// 槽子
/// </summary>
[System.Serializable]
public class Slot
{
    /// <summary>
    /// 槽子的transform
    /// </summary>
    public Transform transform;
    /// <summary>
    /// 槽子的位置
    /// </summary>
    public Vector2 position;
    /// <summary>
    /// 槽子存放的内容
    /// </summary>
    public GameObject content;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值