Unity背包道具拖拽(极简版实现)

发布于:2024-12-18 ⋅ 阅读:(53) ⋅ 点赞:(0)

(感觉Csdn代码页面可以再大一点或者加个放大功能 不然得划着看不太舒服)

1.关键接口,三个拖拽相关的

2.关键参数,PointerEventData

一直没仔细看过,其实有包含鼠标相关的很多参数,鼠标点击次数,判断是否拖动等等。这里是使用了pointerCurrentRaycast,也就是当前触碰到的物体的信息,注意是当前,也就是只有一个,所以当我们想要拖动一个道具放到格子中的时候,一定会先触碰到当前道具,所以还需要CanvasGroup组件,当道具开始挪动的时候,将blocksRaycasts设为false,也就是当前道具不能被射线检测,这样就可以检测到道具后面的槽位了

3.关于道具拖动,有两种实现方式

第一种 transform.postion = event.position

第二种 rectTransform.anchoredPosition += eventData.delta;

eventData.delta:鼠标在一帧内的移动距离

这样做会使UI元素在每一帧都根据鼠标的移动更新自己的位置,从而实现了拖拽的效果。

4.基本概念要搞清楚

rectTransform.anchoredPosition:表示Rect Transform的中心点相对于锚点的位置。

event.position:是基于屏幕坐标的,代表了当前鼠标在屏幕上的位置

transform.position它是世界坐标嘛对吧,为什么可以直接使用呢?

其实最稳妥的做法是将event.position通过Camera.ScreenToWorldPoint转换为世界坐标,再给transform.position赋值,在这里没有出错是因为,Canvas 设置为 Screen Space - Overlay 模式时,Canvas的内容会像UI元素一样,直接显示在屏幕的最上层,不受场景中摄像机视角的影响,也就是所有的子元素都是相对于屏幕坐标系的,而不是相对于世界坐标系的。因此,在这种情况下,eventData.position 提供的屏幕坐标可以直接应用于这些 UI 元素的 Transform 组件。

public class UIBagItem : MonoBehaviour, IBeginDragHandler, IEndDragHandler, IDragHandler
{
    private Vector3 startVec;
    public Image img;
    public Text level;
    private ItemInfo info;
    public Transform itemTrans;
    public Transform pastParent;
    private RectTransform rectTransform;
    void Awake()
    {
        rectTransform = GetComponent<RectTransform>();
    }

    public void Init(int id, int level, Transform parent)
    {
        this.info = DataManager.Instance.itemInfo[id - 1];
        this.img.sprite = Resources.Load<Sprite>(Config.bagPath + info.name);
        this.level.text = level.ToString();
        this.transform.parent = pastParent = parent;
        this.rectTransform.anchoredPosition = Vector2.zero;
        this.itemTrans = GameObject.Find("ItemTransform").transform;
    }
    public void OnBeginDrag(PointerEventData eventData)
    {
        //鼠标点击的点 pointerEventData
        this.transform.SetParent(itemTrans);
        this.transform.position = eventData.position;
        this.GetComponent<CanvasGroup>().blocksRaycasts = false;
    }

    public void OnDrag(PointerEventData eventData)
    {
        //eventData.delta 鼠标拖拽的位移量
        rectTransform.anchoredPosition += eventData.delta;
        Debug.Log(eventData.pointerCurrentRaycast.gameObject.name);
    }

    public void OnEndDrag(PointerEventData eventData)
    {
        this.GetComponent<CanvasGroup>().blocksRaycasts = true;
        GameObject target = eventData.pointerCurrentRaycast.gameObject;
        ItemInfo targetInfo;
        //判断是否是道具
        if (target.name == "UIBagItem(Clone)")
        {
            targetInfo = target.GetComponent<UIBagItem>().info;
            //再判断是否可以合成
            if(this.info.id == targetInfo.id)
            {
                //可以合成就保存数据
                DataManager.Instance.UpdateBagInfo(targetInfo.consumeId, targetInfo.composeId);
                //更新UI 将目标位置的UI更新为合成后的UI
                target.GetComponent<UIBagItem>().Init(targetInfo.composeId, DataManager.Instance.itemInfo[targetInfo.composeId - 1].level,target.transform.parent);
                Destroy(this.gameObject);
            }
            //不能合成就交换位置
            else
            {
                //本物体父节点
                this.transform.SetParent(target.transform.parent);
                //目标物体的父节点 = 本物体记录的父节点
                target.transform.SetParent(this.pastParent);
                //理解为A=B B=C C=A就好了 这里记录一下
                Transform tempParent = this.pastParent;
                //这里更新本物体记录的父节点
                this.pastParent = target.GetComponent<UIBagItem>().pastParent;
                //目标物体记录的父节点
                target.GetComponent<UIBagItem>().pastParent = tempParent;
                //相对于父物体的位置为0所以这样写
                this.rectTransform.anchoredPosition = Vector2.zero;
                //相对于父物体的位置为0所以这样写
                target.GetComponent<UIBagItem>().rectTransform.anchoredPosition = Vector2.zero;
                //不为0的话就把偏移值赋值上去
            }
        }
        //为什么这里判断标签 是因为格子都是复制出来的 名字后面会有个数
        else if (target.tag == "BagSlot")
        {
            this.transform.SetParent(target.gameObject.transform);
            this.rectTransform.anchoredPosition = Vector2.zero;
        }
        //其他区域 直接归原位
        else
        {
            this.transform.SetParent(this.pastParent);
        }
    }
}

网站公告

今日签到

点亮在社区的每一天
去签到