I am making a drag and drop system where 1 click takes 1 item from the stack to your mouse each time but it takes the stack and leaves behind 1 instead of the other way around
The item behavior script makes it so the item follows the mouse cursor. And the Inventory Manager script adds and removes items from the inventory slot and allows stacking
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using TMPro;
public class ItemBehaviour : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
{
[Header("UI")]
[SerializeField]
private Image image;
public TMP_Text countText;
[HideInInspector]
public Items item;
[HideInInspector]
public int count = 1;
[HideInInspector]
public Transform parentAfterDrag;
private ItemBehaviour clone;
private void Start()
{
InitialiseItem(item);
}
public void RefreshCount()
{
if (count > 1)
{
countText.text = count.ToString();
}
else
{
countText.text = "";
}
}
public void InitialiseItem(Items newItem)
{
item = newItem;
image.sprite = newItem.sprite;
RefreshCount();
}
public void OnBeginDrag(PointerEventData eventData)
{
bool isShiftPressed = Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift);
if (!isShiftPressed)
{
// Drag only one item
if (count > 1)
{
// Create a clone of the item
clone = Instantiate(this, transform.parent);
clone.count = 1;
clone.InitialiseItem(item);
clone.RefreshCount();
// Update the count of the original item
count--;
RefreshCount();
}
}
else
{
// Drag the whole stack
clone = this;
}
// Update UI
image.raycastTarget = false;
parentAfterDrag = transform.parent;
transform.SetParent(transform.root);
RefreshCount();
}
public void OnDrag(PointerEventData eventData)
{
transform.position = Input.mousePosition;
}
public void OnEndDrag(PointerEventData eventData)
{
image.raycastTarget = true;
transform.SetParent(parentAfterDrag);
// Handle dropping the item
if (clone != this)
{
// If dragging a clone (one item), the original stack is left with updated count
if (count <= 0)
{
Destroy(gameObject);
}
}
else
{
// Otherwise, the item is left behind with updated count
RefreshCount();
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class InventoryManager : MonoBehaviour
{
public InventorySlot[] inventorySlots;
public GameObject inventoryItemPrefab;
[SerializeField]
private int maxitems;
[SerializeField]
private int currentItems;
private void Update()
{
UpdateCurrentItems();
}
public bool AddItem(Items item)
{
if (currentItems < maxitems)
{
// Check if the item can be stacked in an existing slot
for (int i = 0; i < inventorySlots.Length; i++)
{
InventorySlot slot = inventorySlots[i];
ItemBehaviour itemInSlot = slot.GetComponentInChildren<ItemBehaviour>();
if (itemInSlot != null && itemInSlot.item == item && itemInSlot.item.stackable == true)
{
itemInSlot.count++;
itemInSlot.RefreshCount();
currentItems++;
return true;
}
}
// Check for an empty slot to place the new item
for (int i = 0; i < inventorySlots.Length; i++)
{
InventorySlot slot = inventorySlots[i];
ItemBehaviour itemInSlot = slot.GetComponentInChildren<ItemBehaviour>();
if (itemInSlot == null)
{
SpawnItem(item, slot);
currentItems++;
return true;
}
}
return false;
}
else
{
Debug.Log("Storage is full");
return false;
}
}
// Spawns item in inventory
void SpawnItem(Items item, InventorySlot slot)
{
GameObject newItemGO = Instantiate(inventoryItemPrefab, slot.transform);
ItemBehaviour itemBehaviour = newItemGO.GetComponent<ItemBehaviour>();
itemBehaviour.InitialiseItem(item);
}
void UpdateCurrentItems()
{
currentItems = 0;
foreach (InventorySlot slot in inventorySlots)
{
ItemBehaviour[] itemsInSlot = slot.GetComponentsInChildren<ItemBehaviour>();
foreach (ItemBehaviour item in itemsInSlot)
{
currentItems += item.count;
}
}
}
// Check if the inventory has the specified item and quantity
public bool HasItem(Items item, int quantity)
{
foreach (InventorySlot slot in inventorySlots)
{
ItemBehaviour itemInSlot = slot.GetComponentInChildren<ItemBehaviour>();
if (itemInSlot != null && itemInSlot.item == item && itemInSlot.count >= quantity)
{
return true;
}
}
return false;
}
// Remove the specified quantity of an item from the inventory
public void RemoveItem(Items item, int quantity)
{
foreach (InventorySlot slot in inventorySlots)
{
ItemBehaviour itemInSlot = slot.GetComponentInChildren<ItemBehaviour>();
if (itemInSlot != null && itemInSlot.item == item)
{
if (itemInSlot.count > quantity)
{
itemInSlot.count -= quantity;
itemInSlot.RefreshCount();
return;
}
else
{
quantity -= itemInSlot.count;
Destroy(itemInSlot.gameObject);
if (quantity <= 0)
{
return;
}
}
}
}
}
}
New contributor
Aric Zhang is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.