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

滑动列表结构如下:

相关推荐
萘柰奈8 小时前
Unity进阶--C#补充知识点--【Unity跨平台的原理】Mono与IL2CPP
unity·c#·游戏引擎
淡海水9 小时前
【原理】Unity GC 对比 C# GC
unity·c#·gc·垃圾回收
阿赵3D11 小时前
Unity引擎播放HLS自适应码率流媒体视频
unity·游戏引擎·音视频·流媒体·hls
NRatel14 小时前
Unity 游戏提升 Android TargetVersion 相关记录
android·游戏·unity·提升版本
郝学胜-神的一滴15 小时前
Three.js 材质系统深度解析
javascript·3d·游戏引擎·webgl·材质
SmalBox16 小时前
【渲染流水线】[光栅阶段]-[片元着色]以UnityURP为例
unity·渲染
★YUI★1 天前
学习游戏制作记录(玩家掉落系统,删除物品功能和独特物品)8.17
java·学习·游戏·unity·c#
SmalBox1 天前
【渲染流水线】[光栅阶段]-[光栅插值]以UnityURP为例
unity·渲染
谷宇.1 天前
【Unity3D实例-功能-拔枪】角色拔枪(二)分割上身和下身
游戏·unity·c#·游戏程序·unity3d·游戏开发·游戏编程