Inventory Managment/System for a factory game

Hello,

I started working on a factory game (satisfactory, factorio type of games). I Got a building system down and some basic inventory that processes recipes. Now i want to implement a inventory system.

Started off with a Inventory base, then using that made BuildingInventory and PlayerInventory. The thing is that buildin Inventory has to have input output slots. and the Player just normal slots with hotbar. I got a supper basic version to work with dynamic UI Slots but hit a wall when needing to transfer between the two inventories then AI got involved and messed it all up. So i reverted the changes and back to the simple system

Items are setup using SO and recipes are setup using a list of a struct or class with ItemSO and amount

Do i setup one InventoryManager, then use a Interface or something similar?

Are there any tutorials, guides or even books on Inventory systems that persist if the gameobject is not loaded / rendered.

You “want” to, or you want to have one? There are plenty solutions already available. Of course DIY has its merits, but don’t just blindly roll your own because it’s never as simple as one would expect.

You just paraphrased some fragments of your current setup. There’s just not enough detail to provide concrete suggestions.

Just one general rule of thumb: data, data, data.

Decouple your data from the architecture and anything you build around it will be a lot easier. You probably don’t even need a “base” class, nor would you need separate classes for Building, Player, etc inventories. Think database, not OOP.

Like I said, data. You can persist data any way you like. Whatever code uses it and what that code’s lifetime is won’t matter anymore.

This can help you decide what kind of a system and level of complexity you need. As CodeSmile already posted above, these things are “never as simple as one would expect.”

These things (inventory, shop systems, character customization, dialog tree systems, crafting, ability unlock systems, tech trees, etc) are fairly tricky hairy beasts, definitely deep in advanced coding territory.

The following applies to ALL types of code listed above, but for simplicity I will call it “inventory.”

Inventory code never lives “all by itself.” All inventory code is EXTREMELY tightly bound to prefabs and/or assets used to display and present and control the inventory. Problems and solutions must consider both code and assets as well as scene / prefab setup and connectivity.

If you contemplate late-delivery of content (product expansion packs, DLC, etc.), all of that has to be folded into the data source architecture from the beginning.

Inventories / shop systems / character selectors all contain elements of:

  • a database of items that you may possibly possess / equip
  • a database of the items that you actually possess / equip currently
  • perhaps another database of your “storage” area at home base?
  • persistence of this information to storage between game runs
  • presentation of the inventory to the user (may have to scale and grow, overlay parts, clothing, etc)
  • interaction with items in the inventory or on the character or in the home base storage area
  • interaction with the world to get items in and out
  • dependence on asset definition (images, etc.) for presentation
    → what it looks like lying around in the world? In a chest? On a shelf?
    → what it looks like in the inventory window itself?
    → what it looks like when worn by the player? Does it affect vision (binoculars, etc.)
    → what it looks like when used, destroyed, consumed?

Just the design choices of such a system can have a lot of complicating confounding issues, such as:

  • can you have multiple items? Is there a limit?
  • if there is an item limit, what is it? Total count? Weight? Size? Something else?
  • are those items shown individually or do they stack?
  • are coins / gems stacked but other stuff isn’t stacked?
  • do items have detailed data shown (durability, rarity, damage, etc.)?
  • can users combine items to make new items? How? Limits? Results? Messages of success/failure?
  • can users substantially modify items with other things like spells, gems, sockets, etc.?
  • does a worn-out item (shovel) become something else (like a stick) when the item wears out fully?
  • etc.

Your best bet is probably to write down exactly what you want feature-wise. It may be useful to get very familiar with an existing game so you have an actual example of each feature in action.

Once you have decided a baseline design, fully work through two or three different inventory tutorials on Youtube, perhaps even for the game example you have chosen above.

Breaking down a large problem such as inventory:

If you want to see most of the steps involved, make a “micro inventory” in your game, something whereby the player can have (or not have) a single item, and display that item in the UI, and let the user select that item and do things with it (take, drop, use, wear, eat, sell, buy, etc.).

Everything you learn doing that “micro inventory” of one item will apply when you have any larger more complex inventory, and it will give you a feel for what you are dealing with.

Breaking down large problems in general:

The moment you put an inventory system into place is also a fantastic time to consider your data lifetime and persistence. Create a load/save game and put the inventory data store into that load/save data area and begin loading/saving the game state every time you run / stop the game. Doing this early in the development cycle will make things much easier later on.

Various possible inventory data structures in Unity3D:

1 Like

Do you know any guides and material that cover this topic. I want to do it DIY instead of the shelf solution.

Current system that i have just to test if everything works, Its just list that i add remove items.

And dont have any experience in this type of games. Mainly FPS games and a bit of Multiplayer with that.

I was thinking that i would have a “base” that has basic function for moving items then for specific building types add extra functions and Lists for inventorys

Not necessarily, you can write a good system for managing inventory items purely with static classes/methods operating on data.

For a Satisfactory game you have:

  • Resources - generate items over time, this may even include animals as they may be a form of resource too. Also specifies whether the source is replenishable, infinite or finite.
  • Items (a single mesh may represent 1-n items)
  • Item attributes - some items are multi-use, for instance you can have multiple items be a “consumable energy source” with a varying amount of energy provided (leaves, wood, coal, …). For that you can define an attribute “energy source” and provide the amount of energy per use.
  • Ports - this is where you plug in the item of the desired type, these specify allowed types such as “any” or “copper wire” or “energy source”

Best start by defining what data you need (item, recipe, resources, etc). Then build the systems around modifying that data. Start with the simplemost resource transfer - this doesn’t even need a visualization, you can (and should) make that work purely from a data perspective. Think of acquiring coal over time, the player manually adds that into a burner, this generates electricity (another resource), this powers a miner (and needs a powerline connection), miner extracts iron ore over time, and this ore gets fed into some machine through a conveyor, which then turns the iron ore into iron ingots and places them at the output port, which is a single inventory slot and gets filled when there is no conveyor attached or the conveyor is “full”.

You’ll have enough on your hands to make this part work and how to connect the dots. But it would be a good exercise to think of all the resource aspects, especially the less obvious ones like animal spawners and electricity (imagine this as having infinite speed on the power line “conveyor” - it just needs a connection). That way you’ll be able to meld many things together rather than having special case code for things that in reality are generalizable.

1 Like

For a factory game you’d want to pretty much be able to represent as much as your game state entirely as data. There should be a clear distinction, and really, it will mean most of your game world just acts as entry points into the data layer. You can have a top-most data object that contains most, if not all of the data of your game world.

An assembly machine game object/prefab in the game world, for example, would just have some means to hook into its respective backing data, so it can show the user UI on what’s going on, and naturally allow the user to manipulate what’s going on through it.

The same concept can apply with an inventory system. In my current project, any ‘container’ in the game world doesn’t directly handles its content. It simply has an ID that can look up its contents within a greater, purely data registry of container contents. It makes it a lot easier to implement systems that require the contents of one or more container, as you don’t have any game-object-ey things in the way.

And if you’re smart, you can make all this data innately serializable, and thus your save games are much easier to implement.

1 Like

The issue with inventories are they are pretty easy to manage in data, the issue is syncing that with a ui and also handling serialization.

I would recommend having an entire system with the saving/ loading working while your making your data, as that’s the core of inventories.

I found this https://youtu.be/svoXugGLFwU?si=xKT5slJPptg9ZbNm series to me it looks like the reight direction on how he explained it.

One helpful note, as so many this author is putting all the data as fields into a SO:

By default I don’t do that anymore but rather pack all these fields in a [Serializable] struct and that struct is the only field in the SO.

The benefit of doing so is that you can pass around your data as is, without the SO “attached”. This has many benefits, such as being able to modify any of the fields at runtime without applying this modification to everything using the SO.

For instance, you may find you need to alter the DisplayName or Icon at some point, or raise the MaxStackSize but only for a particular machine, or just for the remote player’s inventory but not the local player’s inventory. Reasons are aplenty. In that case, you can just modify the struct fields without affecting other machines/players.

Note that I personally prefer struct because I tend to want to leave the path towards Jobs open and am familiar with the pass-by-value caveats. But it can also be a class and passed by reference.

2 Likes