Simple Inventory System

Hey all.

So I’ve been bangin’ my head against this for some time. Watched countless tutorials but none actually seems to explain this sufficiently well.

I’m trying to patch together an inventory system with a few important characteristics. It also lacks a number of common characteristics.

NOTE: I’m not necessarily looking for a complete solution but a solid idea for architecture.

This is the function I’m looking for.

  • Possible to easily expand with more items (I’m thinking scriptable objects).
  • Possible to instantiate a populated inventory on a procedurally generated object. The specific items will be random (from a non-random list) with a random float amount (randomized in specific ranges).
  • Possible to on given command take “amount” of “item” from inventory1 to inventory2.

Going forward I want to be able to craft, save/load and access data from a GUI. For now the ability to debug amounts and se what’s going on in the inspector is fine.

My suggestion in broad strokes:

  • A scriptable object “Item” holding recourceSpecific data.
  • A class “itemInstance” that holds the item and amount.
  • An “inventory” class containing a List/Dictionary/Hashtable.

Any thoughts on a general structure (or specific scripts) would be greatly appreciated. The specific coding in its self I think I can handle.

Below is my feeble attempt. The Inventory-class contains short notes but like I said: What should the architecture look like?

using UnityEngine;

[CreateAssetMenu(fileName = "New Item", menuName = "Inventory/New Item")]
public class Item : ScriptableObject
{
    public int itemID;
    public string itemName;
    public float itemWeight;
    public Sprite itemSprite;
    [TextArea]
    public string itemDescription;
}

[System.Serializable]
public class ItemInstance
{
    // Reference to scriptable object "template".
    public Item item;
    // Object-specific data.
    public float amount;

    public ItemInstance(Item item, float amount)
    {
        this.item = item;
        this.amount = amount;
    }
}

And here’s the big one (that doesn’t work).

using System.Collections.Generic;
using UnityEngine;

public class Inventory : MonoBehaviour
{
    //Initiating my inventoryList. For some reason it shows up in the inspector with 0 capacity.
    public List<ItemInstance> inventory = new List<ItemInstance>(10);

    public void AddAmount(Item _item, float _amount)
    {
        for (int i = 0; i < inventory.Count; i++) //Generates a null exception. Why?
        {
            if (inventory[i].item.itemID == _item.itemID) //My code never gets here.
            {
                inventory[i].amount += _amount;
                break;
            }
        }
        InsertItem(_item, _amount); //All tries to "AddAmount" goes directly to "InsertItem".
    }

    public float RemoveAmount(Item _item, float _amount)
    {
        for (int i = 0; i < inventory.Count; i++)
        {
            if (inventory[i].item.itemID == _item.itemID)
            {
                if (inventory[i].amount > _amount)
                {
                    inventory[i].amount -= _amount;
                    return _amount;
                }
                else if (inventory[i].amount <= _amount) //Take more than available.
                {
                    _amount = inventory[i].amount;
                    inventory[i].amount = 0f; //Reduce inventorySlot.amount to zero.
                    inventory.RemoveAt(i); //Remove the item from the inventorySlot.
                    return _amount; //Return whatever amount was available.
                }
            }
        }
        return 0f;
    }

    public void InsertItem(Item _item, float _amount)
    {
        for (int i = 0; i < inventory.Count; i++) //Again the for-loop gives null exception.
        {
            if(inventory[i] == null)
            {
                inventory.Insert(i, new ItemInstance(_item, _amount));
            }
        }
    }
}
1 Like

Lists are not arrays.

Lists always start with Count == 0. Empty. The capacity thing is just a performance optimization.

To add an element to a List you use myList.Add(thing);

That adds the new item to the List.

Off to a good start. :slight_smile: Thank you.

I guess that’s why I’m getting the ”null reference” when trying to iterate through the list (since it’s not populated yet).

Would an array work better for what I’m trying to achieve?

Arrays are generally for when you do not anticipate resizing them.

Lists are for when you anticipate regular changes to the total size of the collection.

Either one could be considered appropriate for different types of inventories.

Also, just for reference, “Simple Inventory System” pretty much does not exist. An inventory system by definition is already a complicated beast, touching on massively-disparate areas of computer science, data storage, data architecture, and user interface, not to mention user experience and usability.

The main thing that I think you’re missing here is that your ItemInstance class is a reference type. Unlike a struct, you need to explicitly instantiate it. Simply creating an array of ItemInstance references doesn’t actually create any instances. To create an ItemInstance you need to use the new operator. For example:

ItemInstance[] items = new ItemInstance[10];

for (int i = 0; i < items.Length; i++) {
  items[i] = new ItemInstance();
}

@Kurt-Dekker Yeah. In the realm of inventories I think this is simpler than most but… Yeah. It sure has proven to be more than I could chew. My game-idea is kindof built around it though…

@preatorBlue I’ll look it over Thanks.

I’ll post here again within 24h if I don’t get some basic functionality.

Thank you both so much for the responses!

Best approach for this is to break things up in this case and implement it in stages:

  1. get the basic minimum data defined (maybe just the name of the item)

  2. lay it out static (eg., give you a preset unchangeable inventory)

  3. give the ability to add stuff to the inventory at runtime

  4. give the ability to remove stuff

  5. etc.

You should be using source control so as you get any tiny chunk of functionality going, you freeze it in time by committing it, so if you screw it up later, you can always revert back.

Personally I use git because it is free and there are tons of tutorials out there to help you set it up.

Here’s how I use git in one of my games, Jetpack Kurt:

https://discussions.unity.com/t/807568/3

Using fine-grained source control as you work to refine your engineering:

https://discussions.unity.com/t/826718/2

Share/Sharing source code between projects:

https://discussions.unity.com/t/719810/2

Setting up the right .gitignore file:

https://discussions.unity.com/t/834885/5

2 Likes

Love it. Thumbs up @Kurt-Dekker .

1 Like

Hey guys. Got much closer!

I ended up revamping the whole thing but I now have the functionality I wanted. Still have many miles to go before I sleep but…

Thanks again! Tagging this as “resolved”. Take care.

1 Like