Best practices for implementing an inventory system in Unity?

I’m working on an inventory system for my game in Unity and would like to follow best practices to ensure scalability, efficiency, and maintainability. My inventory needs to support item stacking, equippable items, and drag-and-drop functionality.

I’m considering using ScriptableObjects for item definitions and List or Dictionary<T, T> for inventory storage. However, I’m unsure about the best way to handle UI updates, persistence (saving/loading inventory state), and performance optimizations for large inventories.

Could experienced developers share their recommended architecture, design patterns (e.g., MVC, ECS), and pitfalls to avoid when implementing an inventory system in Unity? Any code job examples or resources would also be greatly appreciated!

It sounds like you know what you’re doing, so there’s no real best practices, as it’s all situational.

A basic inventory has the data items (all the templats items that you can create with SO), game items ( instances of the items), slots.

Your inventory can be expressed as a serialized structure (item, amount, position) and update to serialized on dirty.

For inventories the slots, item and inventory itself I make MVC.

The biggest one: not thinking about save games ahead of time. If anything, you data structures should be dictated by what you need to save.

Particularly as Unity has the notable restrictions of:

  • We can’t save references to Unity objects to disk
  • We can’t serialize entire Unity objects to disk (save via the JsonUtility class)

So instead you need to come up with a solution that works in your project and your preferences. Such as converting runtime-only data to saveable data and back again (simple, but doesn’t scale), using the your serializer of choice to replace direct references with something else and back again, or a form of indirect references. Probably a number of other options as well.

I’m also currently working on an inventory system. If I was working on a large game like Diablo with a big team then I’d be tempted to use a database. This is mainly to avoid data conflicts if multiple people are entering data (unique id’s for gear etc). Plus it works for multiplayer where the server stores the data you don’t need to worry about losing data with ACID transactions. For a standard local game I’d just stick with Scriptable objects.

One thing I like using are services. I tend to keep them stateless and they work well with patterns like decorators and chain of responsibility. I also like keeping the mutable and immutable data separate so the service makes it easier to use by combining them into a new structure. So I might have something like:

public record Product(int ProductId, int ProductName, int Price, int OwnedQuantity); 

interfact IStoreService
{
    Product[] GetProducts();
    void Purchase(int productId, int quantity);
}

Where I have a ProductAsset ScriptableObject that has ProductId, ProductName, Price and other details. Then I might have a class that I save, probably using json e.g. PlayerData. This contains my inventory of ids/quantities, currency etc.

One thing I’ve been tempted to try is making my data in a ECS style. So instead id’s for type I could just have a common entity id. So my save is mainly just a list of entity id’s and quantities. So I might have something like entityId = new int[] {1,4,5, 2}, quantity= new int[] {4, 2, 1, 1}. The items could then be anything e.g. 4 potions, weapons, gold, key item, quest completed, flag triggered, character unlocked etc. So I might have a recipe that takes entities and output entities. This would allow for things like potion = 5xherbs, weapon upgrade = 100xgold + baseWeapon + silver, monster fusion = monsterA + monsterB. One downside of this is that I’d lose filtering when assigning items and I could also create some nasty bugs e.g. could make a recipe that crafts my entire party into a rock.

1 Like