Better system for drag and drop UI?

Currently my game has an Inventory with an Inventory UI and Equipment (what the Player has equipped) with current equipment UI. I also plan to have a ratchet and clank style selection wheel where the Player can put weapons into slots and select those weapons for equipping.

My current system for drop and drop UI is thus. I have an ItemDropHandler attached to my canvas, which handles all the dropping of items.

using System.Collections;
using System.Collections.Generic;
using UnityEngine.EventSystems;
using UnityEngine;

public class ItemDropHandler : MonoBehaviour, IDropHandler
{
    public static ItemDropHandler instance;
    List<RectTransform> inventorySlotTransforms;
    [SerializeField] GameObject[] inventorySlots;
    public InventoryItem itemDragging;
    public GameObject DraggedFrom;
    [SerializeField] GameObject[] currentEquipmentSlots;
    Inventory inventory;

    void Awake(){
        instance = this;
    }
    void Start(){
        inventorySlots = GameObject.FindGameObjectsWithTag("InventorySlot");
        inventory = GameObject.Find("Player").GetComponent<Inventory>();
        currentEquipmentSlots = GameObject.FindGameObjectsWithTag("CurrentEquipmentSlot");
    }

    public void setItem(InventoryItem item){
        itemDragging = item;
    }
    public void OnDrop(PointerEventData eventData){

        bool found = false;

        RectTransform invPanel = transform as RectTransform;

        if(!RectTransformUtility.RectangleContainsScreenPoint(invPanel, Input.mousePosition)){

        }
        else{
        }

        print(itemDragging.name);

        foreach (var slot in inventorySlots)
        {
            if(!found){
                var slotTransform = slot.transform as RectTransform;
                if(RectTransformUtility.RectangleContainsScreenPoint(slotTransform, Input.mousePosition)){
                    if(DraggedFrom.tag == "InventorySlot"){
                        print("Adding item");
                        int oldIndex = slot.GetComponent<InventorySlot>().slotIndex;
                        int newIndex = DraggedFrom.GetComponent<InventorySlot>().slotIndex;

                        slot.GetComponent<InventorySlot>().AddItem(itemDragging);
                        DraggedFrom.GetComponent<InventorySlot>().ClearSlot();

                        inventory.swapSlots(oldIndex, newIndex);
                        inventory.setPositions();
                        found = true;
                    }
                    else{
                        print("Swapping");
                        int Index = slot.GetComponent<InventorySlot>().slotIndex;
                        inventory.replace(Index, itemDragging);
                    }
                }
            }
        }
    }
}

and a ItemDragHandler attached to the icon of the UI of each of my inventorySlots and currentEquipment slots

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;

public class ItemDragHandler : MonoBehaviour, IDragHandler, IEndDragHandler
{
    [SerializeField] RectTransform m;
    public InventoryItem item;
    public ItemDropHandler itemDropHandler;

    void Start(){
        itemDropHandler = ItemDropHandler.instance;
    }
    public void OnDrag(PointerEventData eventData){
        transform.position = new Vector3(Input.mousePosition.x, Input.mousePosition.y, -5);

        if(gameObject.transform.parent.parent.tag == "CurrentEquipmentSlot"){
            item = transform.parent.parent.GetComponent<EquipmentSlotUI>().item;
        }

        else{
            item = transform.parent.parent.GetComponent<InventorySlot>().item;
        }

        print("Set tag: " + transform.parent.parent.gameObject.tag);
      
        itemDropHandler.setItem(item);
        itemDropHandler.DraggedFrom = transform.parent.parent.gameObject;
    }

    public void OnEndDrag(PointerEventData eventData){
        m.anchoredPosition = Vector2.zero;
    }
}

I’m getting a lot of problems with this. Dragging and dropping to and from the Inventory works fine. However i don’t like how i iterate through each inventory slot and check the rect transform.

I’m also having a lot of problems with my inspector. ‘ItemDragging’ and ‘DraggedFrom’ NEVER change in the inspector even though they are definitely changing in my code. I have been having a lot of problems with my inspector recently. For the first time in a long time i have to restart Unity to fix issues. The inspector won’t properly load things from code.

This is what i mean ^. ItemDragging and DraggedFrom never change in the inspector. I have debugged and they change every single time in the script itself.

When i drag from my equipment, i get object reference exceptions regardless of where i drop the item, even though the item is set exactly the same way as the Inventory items, just with a different parent script.

If i keep going down this route i’ll have to manually write drag and drop interactions between each of the different item places (inventory, currentEquipment, selectionWheel) because they all have different parent scripts (the same drag scripts though).

Is there a better system i could use for dragging and dropping?

Thanks.

Make sure you’re looking at the right instance of ItemDropHandler.

I’d probably set up the script so that all of the different types of valid drop locations inherit from the same base class, and then have a central drag manager that controls the drag and drop of items between everything, rather than splitting up drag and drop into two separate scripts.

1 Like