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);
        }
    }
}

滑动列表结构如下:

相关推荐
郝学胜-神的一滴7 小时前
基于OpenGL封装摄像机类:视图矩阵与透视矩阵的实现
c++·qt·线性代数·矩阵·游戏引擎·图形渲染
EQ-雪梨蛋花汤12 小时前
【Unity笔记】Unity 编辑器扩展:打造一个可切换 Config.assets 的顶部菜单插件
unity·编辑器·游戏引擎
SmalBox12 小时前
【URP】UnityHLSL顶点片元语义详解
unity·渲染
在路上看风景1 天前
9. Mono项目与Unity的关系
unity
在路上看风景1 天前
1.12 Memory Profiler Package - Summary
unity
SmalBox1 天前
【URP】Unity Shader Tags
unity·渲染
极客柒2 天前
Unity 塔防自用可视化路点寻路编辑器
unity·编辑器·游戏引擎
程序猿多布2 天前
Unity AssetBundle详解
unity·assetbundle
萘柰奈2 天前
Unity学习----【进阶】Addressables(二)--加载资源与打包及更新
学习·unity
lvcoc2 天前
unity 接入火山引擎API,包括即梦AI
windows·unity·ai·火山引擎