unity实现背包拖拽排序
在原本的滑动列表上层创建一个相同的dragParentRect层,用来在拖拽时将GameObject置顶,创建一个空白的空物体用来占位,_parentRect就是滑动列表的Content。
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);}}
}
滑动列表结构如下: