1
\$\begingroup\$

In my inventory system I want to be able to drag and drop items into inventory slots.

I managed to make it work, but only in a weird way:

  • When the player starts dragging, it picks up the item and it follows the mouse's position.

  • When they release the button outside the inventory, the item's position is restored to the slot from which it was picked up.

    I use GameObject mouseReleasedObject = eventData.pointerCurrentRaycast.gameObject; to detect whether the drag was released over an inventory slot.

  • The problem is that when the player drops it on a possible inventory slot, the same "restore to previous slot" behaviour happens.

    That's because the mouse is top of the dragged item and the slot as well but the item is rendered above everything else.

How can I make the dragging ignore the item itself, and detect the slot underneath?

Start dragging:

    public void OnBeginDrag(PointerEventData eventData)
    {
        GameObject draggedObject = eventData.rawPointerPress;
        if(draggedObject.GetComponent<RectTransform>() is null) return;

        if(draggedObject.tag == "InventoryItem")
        {
            Debug.Log("InventoryItem drag has started!");
            dragStartSlot = draggedObject.transform.parent.gameObject;
            draggedItem = draggedObject;
            draggedItem.transform.SetParent(canvas.transform);
            draggedItem.transform.SetAsLastSibling();

        }
    }

End dragging:

    public void OnEndDrag(PointerEventData eventData)
    {
        
        GameObject mouseReleasedObject = eventData.pointerCurrentRaycast.gameObject;
        if(draggedItem is null) return;
        Debug.Log("Released at: "+mouseReleasedObject.gameObject.name);
        if(mouseReleasedObject.transform.tag == "InventorySlot")
        {
            if(mouseReleasedObject.transform.childCount < 1)
            {
                //  the inventory slot is empty, we place here the item!
                draggedItem.transform.SetParent(mouseReleasedObject.transform);
                draggedItem.GetComponent<RectTransform>().localPosition = Vector3.zero;
            }
            else
            {
                //  the inventory slot is taken, we swap the items!
            }
        }
        else
        {
            //  the item is not released on a proper slot, we restore it's position! 
            draggedItem.transform.SetParent(dragStartSlot.transform);
            draggedItem.GetComponent<RectTransform>().localPosition = Vector3.zero;
        }
    }
\$\endgroup\$
4
  • \$\begingroup\$ Can your item hover over two inventory slots at once? When you pick it up, does it get centered on your mouse or stays relative at the same position from where you pick it up (mouse to item)? \$\endgroup\$
    – Zibelas
    Mar 5 at 18:27
  • \$\begingroup\$ 1. No it can't 2. It's centered on the mouse. \$\endgroup\$
    – shlime
    Mar 5 at 18:29
  • \$\begingroup\$ You are allowed to post your own solution as an answer which is the normal format to mark a question as solved and not include the solution as an edit to the question \$\endgroup\$
    – Zibelas
    Mar 5 at 19:22
  • \$\begingroup\$ @shlime To rephrase Zibelas's comment: please post your solution as an answer, and mark it as the correct answer. \$\endgroup\$
    – Kevin
    Mar 5 at 22:22
1
\$\begingroup\$

My solution for this problem is using the Canvas' Graphic Raycaster Component:

public void OnEndDrag(PointerEventData eventData)
    {

        bool itemHasBeenPlaced = false;
        var results = new List<RaycastResult>();
        graphicRaycaster.Raycast(eventData, results);
        foreach(var hit in results)
        {
            if(hit.gameObject.transform.tag == "InventorySlot")
            {
                if(hit.gameObject.transform.childCount < 1)
                {
                    //  the inventory slot is empty, we place here the item!
                    draggedItem.transform.SetParent(hit.gameObject.transform);
                    draggedItem.GetComponent<RectTransform>().localPosition = Vector3.zero;
                    itemHasBeenPlaced = true;
                }
                else
                {
                    //  TODO: the inventory slot is taken, we swap the items!
                    Debug.Log("the inventory slot is taken, we swap the items!");
                    itemHasBeenPlaced = true;
                }
            }
        }
        if(!itemHasBeenPlaced)
        {
            //  the item is not released on a proper slot, we restore it's position! 
            draggedItem.transform.SetParent(dragStartSlot.transform);
            draggedItem.GetComponent<RectTransform>().localPosition = Vector3.zero;
        }



    }
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.