unity实现背包拖拽排序

在原本的滑动列表上层创建一个相同的dragParentRect层,用来在拖拽时将GameObject置顶,创建一个空白的空物体用来占位,_parentRect就是滑动列表的Content。

cs 复制代码
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

public class EntryNodeGo : MonoBehaviour,IBeginDragHandler, IDragHandler, IEndDragHandler
{
    public TMP_Text msg;
    public Button editBtn;
    public Button deleteBtn;
    public GameObject blank;

    private int _id;
    private int _index;
    private Vector2 _dragOffset;
    private RectTransform _rectTransform;
    private RectTransform _parentRect;
    private RectTransform _dragParentRect;
    private GameObject _blank;
    private Vector2 _cellSize;
    private Vector2 _spacing;
    private RectOffset _padding;
    private const int HorizontalCount = 4;

    private void Start()
    {
        _rectTransform = transform as RectTransform;
        _parentRect = transform.parent as RectTransform;
        GridLayoutGroup gridLayoutGroup = _parentRect.GetComponent<GridLayoutGroup>();
        _padding = gridLayoutGroup.padding;
        _cellSize = gridLayoutGroup.cellSize;
        _spacing = gridLayoutGroup.spacing;
    }
    
    public void Init(int id, int index,RectTransform dragParentRect)
    {
        _id = id;
        _index = index;
        _dragParentRect = dragParentRect;
        msg.text = $"Entry {_id} \nindex {_index}";
    }

    public void OnBeginDrag(PointerEventData eventData)
    {
        if (eventData.button == PointerEventData.InputButton.Left)
        {
            ExecuteEvents.ExecuteHierarchy(transform.parent.gameObject, eventData, ExecuteEvents.beginDragHandler);
        }
        else if (eventData.button == PointerEventData.InputButton.Right)
        {
            _index = transform.GetSiblingIndex();
            RectTransformUtility.ScreenPointToLocalPointInRectangle(
                _dragParentRect, eventData.position, eventData.pressEventCamera, out var localPoint);
            _dragOffset = (Vector2)_rectTransform.localPosition - localPoint;
            _dragOffset.y += _parentRect.localPosition.y;
            transform.SetParent(_dragParentRect, true);
            _blank = Instantiate(blank,_parentRect);
            _blank.transform.SetSiblingIndex(_index);
        }
    }

    public void OnDrag(PointerEventData eventData)
    {
        if (eventData.button == PointerEventData.InputButton.Left)
        {
            ExecuteEvents.ExecuteHierarchy(transform.parent.gameObject, eventData, ExecuteEvents.dragHandler);
        }
        else if (eventData.button == PointerEventData.InputButton.Right)
        {
            // 算出新的局部位置
            RectTransformUtility.ScreenPointToLocalPointInRectangle(
                _dragParentRect, eventData.position, eventData.pressEventCamera, out var localPoint);
            Vector2 newPos = localPoint + _dragOffset;

            // 限制在父物体矩形范围内
            Rect rect = _dragParentRect.rect;
            Vector3 min = rect.min;
            Vector3 max = rect.max;

            // 考虑子物体自身尺寸
            Vector2 halfSize = _rectTransform.rect.size * 0.5f;

            newPos.x = Mathf.Clamp(newPos.x, min.x + halfSize.x, max.x - halfSize.x);
            newPos.y = Mathf.Clamp(newPos.y, min.y + halfSize.y, max.y - halfSize.y);

            _rectTransform.localPosition = newPos;

            int horizontalIndex = (int)((newPos.x - _padding.left)/(_cellSize.x + _spacing.x));
            float y = Mathf.Abs(newPos.y) + _cellSize.y/2;
            int verticalIndex = Mathf.RoundToInt((y - _padding.top + _parentRect.localPosition.y)/(_cellSize.y + _spacing.y));
            verticalIndex = Mathf.Max(1, verticalIndex);
            _index = (verticalIndex - 1) * HorizontalCount + horizontalIndex;
            _blank.transform.SetSiblingIndex(_index);
        }
    }

    public void OnEndDrag(PointerEventData eventData)
    {
        if (eventData.button == PointerEventData.InputButton.Left)
        {
            ExecuteEvents.ExecuteHierarchy(transform.parent.gameObject, eventData, ExecuteEvents.endDragHandler);
        }
        else if (eventData.button == PointerEventData.InputButton.Right)
        {
            Destroy(_blank);
            transform.SetParent(_parentRect, true);
            transform.SetSiblingIndex(_index);
        }
    }
}

滑动列表结构如下:

相关推荐
魔士于安19 分钟前
unity 骷髅人 连招 武器 刀光 扭曲空气
游戏·unity·游戏引擎·贴图·模型
洛阳吕工2 小时前
从 micro-ROS 到 px4_ros2:ROS2 无人机集成开发实战指南
游戏引擎·无人机·cocos2d
风酥糖3 小时前
Godot游戏练习01-第29节-游戏导出
游戏·游戏引擎·godot
瑞瑞小安3 小时前
Unity功能篇:文本框随文字内容动态调整
ui·unity
南無忘码至尊3 小时前
Unity学习90天-第7天-学习委托与事件(简化版)
学习·unity·游戏引擎
君莫愁。3 小时前
【Unity】解决UGUI的Button无法点击/点击无反应的排查方案
unity·c#·游戏引擎·解决方案·ugui·按钮·button
南無忘码至尊15 小时前
Unity学习90天 - 第 6天 - 学习协程 Coroutine并实现每隔 2 秒生成一波敌人
学习·unity·c#·游戏引擎
张老师带你学16 小时前
unity 老版本资源迁移,第一人称,完整城市,有出身点房内视图,有gun shop视图,urp
科技·游戏·unity·模型·游戏美术
mxwin1 天前
Unity URP 下 UI 特效开发指南 深入探索顶点色、Mask 交互与扭曲特效的实战技巧
ui·unity·游戏引擎·shader
CandyU21 天前
Unity入门
unity·游戏引擎