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

滑动列表结构如下:

相关推荐
老朱佩琪!9 小时前
Unity原型模式
开发语言·经验分享·unity·设计模式·原型模式
老朱佩琪!9 小时前
Unity组合模式
unity·游戏引擎·组合模式
老朱佩琪!9 小时前
Unity装饰器设计模式
unity·设计模式
向宇it10 小时前
【unity游戏开发——网络】unity对接steam,并上传发布游戏版本——Steamworks.NET
游戏·unity·游戏引擎·.net·交互
陈言必行10 小时前
Unity 实战:屏蔽移动平台 UI 点击检测的“坑”与解决之道
ui·unity·游戏引擎
CreasyChan10 小时前
unity-向量数学:由浅入深详解
unity·c#
nnsix10 小时前
Unity Terrain获取关联的TerrainData
unity·游戏引擎
秦奈10 小时前
Unity复习学习笔记(七):NGUI
笔记·学习·unity
老朱佩琪!10 小时前
Unity适配器模式
unity·设计模式·游戏引擎·适配器模式
技术小甜甜1 天前
[Godot] 解决导出APK安装失败的常见问题:深入分析与调试方法
游戏引擎·godot·游戏开发