Question

I am pretty new still with programming and unity in general. I am sure the problem do not have anything to do with unity considering there are only scripts in the project no unity objects.

With that said i have having trouble updating the quantity/stack of and item in the inventory. So i have a drag and drop system. When i drag and item onto another item that is the same i want it to stack. From what i know im doing it right but for some reason it is setting the new stack to all the items in the inventory that is the same as the item i want to stack.

Example i have three of the same potions in the inventory but they all in their own slot. I drag one potion onto another potion. I have a stack of two potions on slot 2 now. But the potion in slot 3 also has a stack of 2 potions. I dont know where this problem is coming from.

First i'm trying to just get everything to work then i will make things more efficient. Meaning as soon as i figure this out i will be converting this to an baseItem class.

So here is my Item class

public class Item{

private string itemName;
private int itemID;

private int itemStack;
private int itemMaxStack;


#region Getters and Setters

public string Name
{
    get { return itemName; }
}

public int ID
{
    get { return itemID; }
}

public int Stack
{
    get { return itemStack; }
    set { itemStack = value; }
}

public int MaxStack
{
    get { return itemMaxStack; }
}


 #region Constructors
public Item ()
{
    itemName = string.Empty;

    itemID = 0;
    itemStack = 0;
    itemMaxStack = 0;

}

public Item (string name, int id,  int stack,
    int maxstack)
{
    itemName = name;
    itemID = id;
    itemStack = stack;
    itemMaxStack = maxstack;

}
#endregion

Next here is my generic Inventory Class

public class Inventory : MonoBehaviour 
{
    public int slotsX; // Number of slots on the X axis. Total slots in inventory is slotsX * slotsY
    public int slotsY; // Number of slots on the Y axis. Total slots in inventory is slotsX * slotsY
    private int slotWidth, slotHeight; // The Width and Height of the slots.
    private int iconWidth, iconHeight; // The Width and Height of the icons in the slots.
    private int iconPaddingX, iconPaddingY; // Adds padding to icons in the inventory so that it is center on the X and Y.
    public GUISkin skin; // The GUI skin for the inventory
    public List<Item> slots = new List<Item>(); // List Array that holds all the slots as Items
    public List<Item> inventory = new List<Item>(); // List Array that holds all the Items;
    private ItemDatabase database; // The database of all the items in the game

    private bool draggingItem; // Checks to see if the item is being dragged in the Inventory
    private string tooltip; // The string that contains all the content displayed in the tooltip.

    private int prevIndex; // Holds index of previous dragged item used for swapping items

    private Item draggedItem; // Holds the Item thats is being dragged in the inventory.


    // Use this for initialization
    void Start () 
    {
        database = GameObject.FindGameObjectWithTag("Item Database").GetComponent<ItemDatabase>();

        slotWidth = slotHeight = 50;
        iconWidth = iconHeight = 40;
        iconPaddingX = 6;
        iconPaddingY = 6;

        InitializeSlots();

        AddItem(1);
        AddItem(2);
        AddItem(2);
        AddItem(2);

    }


     void InitializeSlots ()
    {
        for (int i = 0; i < (slotsX*slotsY); i++)
        {
            slots.Add(new Item());
            inventory.Add(new Item());
        }
    }

    void OnGUI()
    {
        e = Event.current;
        tooltip = "";
        GUI.skin = skin;
        if (showInventory)
        {
            DrawInventory();
        }



    void DrawInventory ()
    {

        int i = 0;

        for (int y = 0; y < slotsY; y++)
        {
            for (int x = 0; x < slotsX; x++)
            {
                Rect slotRect = new Rect(x * slotWidth, y * slotHeight, slotWidth, slotHeight);
                Rect itemRect = new Rect(x * slotWidth+iconPaddingX, y * slotHeight+iconPaddingY, iconWidth, iconHeight);
                Rect labelRect = new Rect(x * slotWidth, y * slotHeight, iconWidth, iconHeight);
                GUI.Box(slotRect, "", skin.GetStyle("inventory-slot"));

                slots[i] = inventory[i];

                if (slots[i].Stackable && slots[i].Stack > 1)
                {
                    GUI.Label(labelRect, slots[i].Stack.ToString(), skin.GetStyle("stack-label"));
                }

                if (slots[i].Name != string.Empty)
                {
                    GUI.DrawTexture(itemRect, slots[i].Icon);
                    //print(slots[i].itemName + "in slot " + (i+1) + " has a total of " + slots[i].itemStack + " stackes.");

                    if (slots[i].Stackable == true)
                    {
                        //InventoryContains(slots[i].itemID);
                    }

                    // Check to see if mouse is hovering over a slot.
                    if (slotRect.Contains(e.mousePosition))
                    {
                        // Show tooltip
                        GenerateTooltip(slots[i]);

                        // If right mouse click and if not dragging an item and if the item is equal to a consumable 
                        // or key then use item.
                        if (e.button == 1 && e.type == EventType.mouseUp && !draggingItem && (slots[i].Type == Item.ItemType.Consumable || slots[i].Type == Item.ItemType.Key))
                        {
                            //inventory[i] = UseConsumable(inventory[i]); // Check UseConsumable method for definition
                        } 

                        // If left mouse click and if dragging and if not draggingItem = false
                        // Then drag item
                        if (e.button == 0 && e.type == EventType.mouseDrag && !draggingItem)
                        {
                            DragItem(i); // Check DragItem method for definition
                        }

                        if (e.isMouse && e.type == EventType.MouseDown && e.clickCount == 2)
                        {
                            print(inventory[i].Stack + " | " + slots[i].Stack);
                        }

                        // If dragging and item and if left mouse click is in up postion
                        if (e.button == 0 && e.type == EventType.mouseUp && draggingItem)
                        {
                            // Stack Items
                            if (slots[i].ID == draggedItem.ID)
                            {

                                StackItem(i);
                            }
                            //Swap Item locations
                            else
                            {
                                inventory[prevIndex] = inventory[i];
                                inventory[i] = draggedItem;
                                draggingItem = false;
                                draggedItem = null;
                            }
                        }
                        else
                        {

                        }
                    }
                }
                else
                {
                    if (slotRect.Contains(e.mousePosition))
                    {
                        if (e.type == EventType.mouseUp && draggingItem)
                        {
                            inventory[i] = draggedItem;
                            draggingItem = false;
                            draggedItem = null;
                        }
                    }
                }


                i++;
            }
        }
    }

     void StackItem (int index)
    {
        int newStack = 0;
        newStack = slots[index].Stack + draggedItem.Stack;
        draggedItem = null;
        draggingItem = false;
        inventory[index].Stack = newStack;
    }

//Adds item by Item ID from the itemDatabase
void AddItem (int id)
{

    for (int i = 0; i < inventory.Count; i++)
    {
        if (inventory[i].Name == string.Empty)
        {
            for (int j = 0; j < database.items.Count; j++)
            {
                if (database.items[j].ID == id)
                {
                    inventory[i] = database.items[j];
                    return;
                }
            }


        }
    }
}

Sorry only the more important things are commented.

Edited:

Here is the Item Database class

public class ItemDatabase : MonoBehaviour {

        public List<Item> items = new List<Item>();


        void Start ()
        {
            items.Add(new Item("Base Potion", 1, 1, 10));
            items.Add(new Item("Magic Potion", 2, 1, 10));

        }
    }

Edited 2: The problem was indeed i was referencing the class. I added a Clone method to that class and a few other modifications then everything worked

 public object Clone ()
{
    Item item = new Item(Name, ID,  Quantity, MaxStack);
    return item;
}
Was it helpful?

Solution

I got a little lost with the code (Not your fault), but I think the problem is a pass by reference / value error. (You can google it if you want, but I'll try to explain)

Passing by reference is what C# does by default. It means this code:

MyClass X = new MyClass();
MyClass Y = X;
X.Value = 0;
Y.Value = 10;
Console.WriteLine(X.Value);
Console.WriteLine(Y.Value);

Will print:

10 
10

This is because Y basically becomes a new way to access X, so if Y is changed, X changes too. I think this is the problem, when you try to stack items, the items are not separate objects, but rather at some point they end up being references to one single object, so thus, when you go to make the quantity of one increase, the quantity of the other increases too.

Edit: Not sure at all, but the problem may be when you add new items from the item database. I think that maybe the item in the item database is a value, and when you add new items to the inventory, they become references - copies of the item in the database.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top