I have tried to make a code where when the user takes an item into their inventory, if the amount of the item stack already in their inventory plus the amount of the item they are trying to take exceeds that item’s max quantity, it will overflow into another stack. For example:
My inventory has five inventory slots,
The first inventory slot has 15 “pine logs” in it,
Logs can only be stacked in groups of 20,
The second inventory slot has a “logging axe” in it which is not a stackable item,
The rest of the inventory slots are empty,
I am trying to add a stack of 11 “pine logs” into my inventory,
Because the 15 logs in the first inventory slot plus the 11 logs I am trying to add exceeds the max stack size of the first inventory slot, and because the second slot is occupied by a different item, the rest of the logs must overflow into the third inventory slot.
I have tried these codes:
The “Item” script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public class Item
{
public string itemName = "", itemDescription = "";
public bool stackable = false;
public int maxQuantity = 1, currentQuantity = 1;
}
The “InventorySlotData” script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public class InventorySlotData
{
public Item storedItem;
}
And finally the “PlayerScript” script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public class PlayerScript : MonoBehaviour
{
[System.Serializable]
public class PlayerData
{
public List<InventorySlotData> inventory = new List<InventorySlotData>();
}
public PlayerData playerData;
public string activeUI = "Main Screen";
private void Start()
{
Item testItem1 = new Item();
testItem1.itemName = "Pine Log";
testItem1.itemDescription = "A basic pine log.";
testItem1.stackable = true;
testItem1.maxQuantity = 20;
testItem1.currentQuantity = 60;
if (AddItem(JsonUtility.FromJson<Item>(JsonUtility.ToJson(testItem1))))
{
Debug.Log("Added item.");
}
}
private void Update()
{
}
public bool AddItem(Item toAdd)
{
if(toAdd.stackable == true)
{
int matchingSlotIndex = playerData.inventory.FindIndex(msi => msi.storedItem.itemName == toAdd.itemName);
if(matchingSlotIndex != -1)
{
if(playerData.inventory[matchingSlotIndex].storedItem.currentQuantity + toAdd.currentQuantity > playerData.inventory[matchingSlotIndex].storedItem.maxQuantity)
{
Debug.Log("Stack is now overflowing.");
Item overflowItem = new Item();
overflowItem = JsonUtility.FromJson<Item>(JsonUtility.ToJson(toAdd));
overflowItem.currentQuantity = playerData.inventory[matchingSlotIndex].storedItem.currentQuantity + toAdd.currentQuantity - playerData.inventory[matchingSlotIndex].storedItem.maxQuantity;
Debug.Log("Overflow ammount is: " + overflowItem.currentQuantity.ToString());
playerData.inventory[matchingSlotIndex].storedItem.currentQuantity = playerData.inventory[matchingSlotIndex].storedItem.maxQuantity;
if (AddItem(JsonUtility.FromJson<Item>(JsonUtility.ToJson(overflowItem))))
{
Debug.Log("Stack overflowed into new slot.");
return true;
}
} else
{
playerData.inventory[matchingSlotIndex].storedItem.currentQuantity += toAdd.currentQuantity;
return true;
}
} else
{
int openSlotIndex = playerData.inventory.FindIndex(osi => osi.storedItem.itemName == "");
if(openSlotIndex != -1)
{
playerData.inventory[openSlotIndex].storedItem = toAdd;
return true;
}
}
}
if(toAdd.stackable == false)
{
int openSlotIndex = playerData.inventory.FindIndex(osi => osi.storedItem.itemName == "");
if(openSlotIndex != -1)
{
playerData.inventory[openSlotIndex].storedItem = toAdd;
return true;
}
}
return false;
}
}
Unfortunately when I run the game Unity crashes. Is there any modification I can make to the code to fix this and make my script working?
Note: the max stack size of the “Pine Log” is 20, I just added the 60 to see if I could make the item overflow into more than one stack.
Unity crashing means that there’s an infinite loop. Since you’re calling AddItem from AddItem, you’re probably not reducing the amount properly.
You’re logging the data that’s going to help you figure out what’s going on, and even if Untiy crashes before you can see the log in the console, the Debug.Log results are still written to a file.
Open Unity, go to your console, hit the drop-down menu in the upper right corner, and hit “open console.log”. Then, run your code, close Unity, and look in the output file. It’ll have a bunch of entries, probably each one with an increasing overflow amount.
When I had a similar problem with my inventory code I tracked it down by using the ‘attach to unity’ button in Visual Studio and stepping through the code line by line until I found where and why the loop was happening.
Debugging can probably help to find the bug very quickly.
I’ve gone through it theoretically with the example from the OP, and it seems you’re running an infinite recursion due to the tiny mistake that do not handle the occurances of full stacks properly.
That is, the attempt to add another 11 logs to the 15 with a max stack size of 20 adds another 5 to the stack of 15, it returns and you subtract those 5 from 11.
Since a slot was available, and you have 6 remaining logs to add, it’ll start over by calling itself.
Then, the match finder (simple first occurance lookup) finds the same slot again, which already contains a full stack, but you only check (stored + current > max), which is true for full stacks as well. The return value will be (max - stored), which is 0.
That is, AddItem returns, the number of items to add stays the same (since 0 was returned), the slot is still available, and so on. It starts all over, running the exact same routine again.
Small side note: It may improve readability if you use local variables instead of accessing the list’s entries via the indexer again and again.
Ok I have made some progress. I can now cause the item being inserted into one inventory slot to overflow into an empty inventory slot. The new problem is that If there are two or more slots with an identical item, it will not fill up those slots before moving into an empty one. Here are some pictures:
The inventory before using the developer add item command:
Note that item ID 0 is pine logs, with a max stack size of 20 and a default stack size of 20. Can someone please help me with these last few parts to fixing the code: