How to Make a Moddable Inventory System in Unity: Part 2 — Functions

Cameron Kroll
7 min readJul 23, 2020

--

Wondering what this is? Here’s the introduction.

Icon made by Freepik from www.flaticon.com

In the last part of this series, we made the scripts that will act as the basis for our inventory system. In this part, we’ll write some of the functions that will let us control our inventory system, including functions to add, remove and use items. With that out of the way, it’s time for us to create our first function, GetItemIndex.

Function #1: GetItemIndex()

First things first, we’ll create one of two central functions to the rest of this tutorial. Within the Inventory class from last time, we’ll create a new function that will return an integer and will have a string called Name as a parameter. Within this function, we’ll create the for loop for (int i = 0; i < Objects.Count; i++) which will run through every entry in the Objects list.

Within this loop, we’ll need to create an if statement that will check if the ObjectName variable associated with the Object that’s associated with that particular InventoryObject matches the Name string.

Finally, if the function finds a match, we will return the item’s index. Otherwise, we’ll send an error saying that the item does not exist and we’ll return -1. Here’s an example of what that should look like:

public static int GetItemIndex(string Name){for (int i = 0; i < Objects.Count; i++){if (Objects[i].ObjectInStack.ObjectName == Name){return i;}}Debug.LogError($"{Name} does not exist");return -1;}

Function #2: ContainsItem()

Next, we are going to create a function to tell us if an item is in our inventory. This function will return a boolean and, like the last function, will have a string called Name as its only parameter. Also, like the last function, this function will have a loop checking if each item’s name matches the Name parameter. The only difference with this function is that it will return true if it finds a match and false if it doesn’t. Here’s what that should look like:

public static bool ContainsItem(string Name){  for (int t = 0; t < Objects.Count; t++)  {    if (Objects[t].Object.ObjectName == Name)    {      return true;    }  }  return false;}

Function #3: NumberOfItems()

Using our two previous functions, we will create a function to return the number of objects in the inventory that match the Name parameter. First, we’ll create a local integer called Output and a for loop that will loop through each item in the inventory. Next, we’ll use an if statement to check if the object’s name matches the Name parameter. If this is true, we’ll add the object’s NumberOfObjects variable to the Output variable. Finally, after the loop, we’ll return the Output variable. Here’s what that code looks like:

public int NumberOfItems(string Name)
{
int Output = 0; for (int t = 0; t < Objects.Count; t++) { if (Objects[t].Object.ObjectName == Name) { Output += Objects[t].NumberOfObjects; } } return Output;}

Function #4: RemoveItem()

Next, we’re going to create another function to remove an item that matches the Name parameter a set number of times. This function will have two parameters; a string called Name and an integer called Num. Within this function, we’ll write the if statement if (NumberOfItems(Name) > 0). If this is true, we’ll run through the while loop while (Num != 0). If this isn’t true, we want to give an error message.

Within this loop, we’ll store the index of the first stack that matches our Name parameter. Next, we’ll want to check if the number of items in that stack is greater than the number of items we want to remove. If this is true, we’ll want to subtract Num from that stack’s NumberOfObjects variable and break out of the loop. If this isn’t true, we’ll check if Num is equal to the number of objects in the stack.

If that is the case, we will remove that entry from the list and break out of the loop. Otherwise, we are going to subtract the number of objects in that stack from Num and remove that stack from the list. This loop will keep repeating until we have removed the right number of items.

Function #6: GetEmptyStack()

This next function is like GetItemIndex, except it returns the first stack that has room in it. First, we’ll have an if-else statement that will check if UseSlots is true.

Next, we’ll paste in our code from GetItemIndex(), but we’ll change if (Objects[i].ObjectInStack.ObjectName == Name) to if (Objects[i].ObjectInStack.ObjectName == Name && Objects[i].NumberOfObjects < StackSize).

Finally, if our first if statement is false, we’ll just call the GetItemIndex function and return that. This is what that looks like:

public static int GetEmptyStack(string Name){  if (UseSlots)  {    for (int i = 0; i < Objects.Count; i++)    {      if (Objects[i].ObjectInStack.ObjectName == Name &&
Objects[i].NumberOfObjects < StackSize)
{ return i; } } return -1; } else { return GetItemIndex(Name); }}

Function #7: GetPossibleObject()

This next function is going to be super simple. It is going to do the exact same thing as GetItemIndex(), but for PossibleObjects instead of Objects. We’ll just paste the code from GetItemIndex and change Objects[i].ObjectInStack.ObjectName to PossibleObjects[i].ObjectName. Here’s what that looks like:

public static int GetPossibleObject(string Name){  for (int i = 0; i < Objects.Count; i++)  {    if (PossibleObjects[i].ObjectName == Name)    {      return i;    }  }  Debug.LogError($”{Name} does not exist”);  return -1;}

Function #8: AddItem()

Our final function for this part of the tutorial will add a certain number of an item to our inventory. This function will have two parameters; a string called Name and an integer called Num.

Firstly, we’ll use our last function to get the position of the object “blueprint” in the PossibleObjects array and store it in a local integer. Next, we’ll use an if statement to check if the object’s position is -1 (this is the default and means the object doesn’t exist). If this is true, we’ll run through the while loop while (Num != 0). Within this while loop, we’ll create an if-else if statement that will determine if a stack of this item that has room in it already exists in the inventory using the GetEmptyStack function. If this is true, we’ll store the item’s index in a local integer.

Within this if statement, we’ll create another if-else statement that will check if UseSlots is true and if the number of items in a stack or the maximum weight/volume is enough using the following code:

if ((UseSlots && Objects[temp].NumberOfObjects + Num <= StackSize) || (UseVolume && MaxVolume + (PossibleObjects[GetPossibleObject(Name)].Volume * Num ) <= MaxVolume) || (UseVolume && MaxVolume + (PossibleObjects[GetPossibleObject(Name)].Weight * Num) <= MaxWeight))

If this is true, we’ll add Num to the stack and stop the function. At this point, we have to add objects to the stack until it’s full. There is a way to use math and a bunch of if statements to make this extremely efficient, and you can do that, but I’m just going to add 1 to the stack and subtract 1 from Num and let the while loop take care of the rest.

At this point, we’ve taken care of all the logic for adding items to existing inventory stacks. Next, we’ll create the logic for adding stacks to your inventory. First, we’ll want to check if there’s enough space in our inventory for the items. To do this, we’ll just check if the number of object stacks in our inventory plus one is less than or equal to our InventorySlots variable. If this is true, we’ll check is Num is less than or equal to the StackSize variable.

If that is true, we’ll add a stack of Num objects using the code Objects.Add(new InventoryObject { NumberOfObjects = Num, ObjectInStack = PossibleObjects[Index] }); and stop the function. If that isn’t true, we’ll create a maximum-sized stack and subtract StackSize from Num. Finally, to avoid infinite loops, we’ll use a return statement to stop the function if there isn’t enough space in our inventory. Here’s what that should look like:

public static void AddItem(string Name, int Num)        //adds item to inventory{  int Index = GetPossibleObject(Name);        //stores the index of the object we're looking for in a local variable  if (Index != -1)        //if the object exists  {    while (Num != 0)    {      int temp = GetEmptyStack(Name);        //store the position of the first stack that has room in it      if (temp != -1)        //if there's a stack that has room in it      {//if there's enough room in the stack  to add Num to it        if ((UseSlots && Objects[temp].NumberOfObjects + Num <= StackSize) || (UseVolume && MaxVolume + (PossibleObjects[GetPossibleObject(Name)].Volume * Num) <= MaxVolume) || (UseVolume && MaxVolume + (PossibleObjects[GetPossibleObject(Name)].Weight * Num) <= MaxWeight))        {          Objects[temp].NumberOfObjects += Num;          return;        } else        {          Objects[temp].NumberOfObjects += 1;          Num -= 1;        }      }      else if (Objects.Count + 1 <= InventorySize)        //if there's enough room in the inventory for another stack      {        if (Num <= StackSize)        //if Num can be fit into one stack        {          Objects.Add(new InventoryObject { NumberOfObjects = Num, ObjectInStack = PossibleObjects[Index] });        //add a stack of size Num          return;        } else        {          Objects.Add(new InventoryObject { NumberOfObjects = StackSize, ObjectInStack = PossibleObjects[Index] });        //add a stack of maximum size          Num -= StackSize;        //subtract maximum stack size from Num        }      } else      {        return;        //if there isn't enough room in the inventory, end the function      }    }  }  Debug.LogError($"{Name} does not exist, try adding it to the list PossibleObjects");}

That’s the end of this part! In the next part, we’ll start getting into reflection and JSON serialization. You’ll have to wait for that though, as I’m participating in the I can’t write but want to tell a story Game Jam — so expect Part 3 by the 17th. Until then, bye.

Other parts in this series:

Introduction

Part 1

--

--

No responses yet