How to manage inventory 'objects' in C# for behind the scenes inventory stuff

In C# I have a static BaseLoot class that uses a dictionary to store predefined loot stats and attributes, using the loots type as an index.

Each time I instantiate a real piece of loot in the game world, it has an instance of a Loot class which derives its initial properties from looking up what they should be in the BaseLoot dictionary.

When the item is picked up, I add the object itself (i.e code object, instance of the Loot class) to a dictionary representing the characters inventory, (or subsequently a chests contents).

This is great as I can use all my accessors to retrieve or modify the item from within the inventory. But if there were 100’s of items in the game world all being kept track of in this manner, does that scale? Does that make sense as a way to handle this in the code? Or does it make more sense to serialise the items stats, store them in a global RealItems dictionary with a unique Id, and in the players inventory just store the id? Then recreate the object whenever I want to operate on it?

Do either of those make sense as designs? Or am I barking up the wrong tree completely?

I have been through a number of tutorials on inventories but I get the idea that the tutorials I have seen are really just creating something that “works” in order to show some basic concepts, rather than designing and writing a system to be robust / extendable / manageable etc in the future. That said, I have no interest in over-complicating it just for the sake of it.

Im not new to programming, but Im fairly new to C#. So I can see ways to do stuff and generally make things work, but I dont have the C# experience to know straight away if theres a better way.

Most new MMO's use object referencing. You have a master table of objects and their properties and you reference the object's ID. This allows you to use a database to store data more efficiently. It also allows for versioning of objects across the entire game, without leaving items (called "pre-patch" items) that have out of date properties.

If you need customization, you make a new object and slot it into the object. In that case, you would have the primary object's ID a slotted object ID (or group of ID's) inside it.

Inventory systems include visible inventory, overloaded inventory, store sales inventory (for buy-back purposes in case of accidental sales), trade inventory, equipped inventory, etc. Some systems have pet inventory slots, a mount slot for what object you're riding, and even an inventory for the mount itself for what it's wearing.

Inventory can be very complex! :)

My online project I’ve been experimenting with does this:
Server launches and loads everything from the database.
Each item in the database knows certain core properties, and has a reference to others. I have a table for things like item type. Everything has a unique id (int), I never expect to have more than 2 billion items.

When I read everything in, I use a dictionary to store the item by its id, for very quick access. Type data is stored according to type. I use dictionaries a lot, arrays when it makes sense. Array access is much faster than dictionary access…but I don’t know that I’m willing to make that change yet, I have to see a real need manifest itself first.

As far as storage…I always keep an eye out on doing things more efficiently. I do have some breathing room, my server is a 64 bit C# app.

So, data is only ever read from the database upon server start, from then on it resides in memory. I expect to use separate threads to update the database at specific intervals.

When you mention keeping track of items in the game…do you really actively have to track a lot of items? In my project, most of my items are in containers…and the ones that are not are either equipped by the player, or sparse in the world. Items that are in containers don’t really need be managed as much as stored items (at least in my situation).

Hi Fred,

I’m trying to do something very similair to your question, but don’t have the coding experience to really get it rolling.

I’m looking for a direction on how to tackle dictionaries giving items stats and attributes. How do I set this up?
My idea now:

-create a baseitem class with an ID and default stats.
-create a dictionary class with the “database” of the stats for all the items in the game
(between 100-200).

as I am making a small point n click-ish game, where (some)items can be picked up and dropped in specific places (containers) I believe I would need a seperate class collecting the location data for each item ID. so:

-create a itemlocation class with the locations of each item in the game.

finally:
-a menu class to visualize each of these items in the (for example)OnGUI
when you open one of these containers.

Looking over this, I have some thoughts that might help. It sounds like this is for a multiplayer environment, so here is how I would handle this.

First, I would have a table (or file, or whatever) that defines my item TYPES and their default values.

Type Name DefaultStr DefaultInt DefaultWis DefaultValue

1 Axe 5 0 0 3

2 Bow 2 3 0 7

3 Biscuit 0 1 2 3

In code (I use C#), I’d have my server read in the data into a dictionary of ItemTypes, by Id.

So, I would have an ItemType class, that stored the type, name, default bonuses, etc. For each item type, I would store its data into a new instance of the itemtype class.

I would then store the itemtypes into a dictionary, with the item type being the key:

Dictionary<int, ItemType> itemTypesByType = new ....

I’m using an int as the key, I don’t expect you will have more than 2 billion types of items eh?

For items:
ItemBase (or whatever), but I wouldn’t derive this from the ItemType. Instead, I would do something like this:

public class ItemBase
{
  private ItemType _ItemType;
  private int _Id;

  public ItemBase(int id, int type)
  {
    _Id = id;
    _ItemType = itemTypesByType[type];

  }
}

That way, the item knows its default info…it doesn’t have to derive from it. I prefer this sort of thing to a lot of oo layers, personally.

Also, notice I assigned an item id. Your server would assign new ids to each item created. From then on, that unique id is assigned to that unique item in the ‘world’.

If you want stuff stored in containers, like a player inventory, a barrel, etc, you will need each item in the world to also have an OwnerId. This would be another int value. It would be the id of the item that “owns” or stores the item.
So let’s say you have a barrel in the world. Id = 1, owner = 0 (it sits on the ground).
You have an apple, id=2. You put it in the barrel. The apple’s ownerid would be set to the barrel, or 1.
If your player has an id (it should), then you would just assign the item owner id to the player id.

So, each ItemBase will also now need a list of children.

List<int> childItems;

This list is not stored in the database, only in memory. We don’t need to store an items children, because we store the parent (ownerid) for each item.
When the server “loads” everything, it would need to load all world items into memory, then do another pass to assign children to parents. This will probably take all of 5 milliseconds.

When the server/game/whatever starts, it would assign all items belonging to each parent as a child.

You mentioned concern about performance. This may not be an issue, because…

When the server tells the client to create an apple on the ground, the client creates an apple gameobject. It addsd the gameobject to a dictionary (I am a big fan of dictionaries), which tracks gameobject by item id.

Dictionary<int, GameObject> gameObjectsByItemId;

Great, now for any item, I can immediately retrieve its gameobject.
When the player picks up the apple, the server assigns the player as the owner. The client removes the apple from the VISIBLE game world (since it is in a container now). The server also adds the apple id (2) to the player’s list of child items. A very quick operation.

Also, track gameobjects in reverse:

Dictionary<GameObject, int> ItemIdsByGameObject;

What does this do? If the player selects any gameobject we created (an apple, a barrel, whatever), we can immediately get the item id. So player clicks on a gameobject. We get the item id this way. Assume the gameObject variable holds the targetted gameobject, which we found via raycast.

int itemID = ItemIdsByGameObject(gameObject);

Now, the client asks the server to change the item’s ownership, while it hides it from view.

When you want the game to display the model/gameobject for a particular item, it’s easy:
Define a list (dictionary if you want haha) where you have a prefab reference, with the item TYPE being the key.

Dictionary<int, GameObject> PrefabsByItemType;

You would do this to add the apple when the client initializes:

PrefabsByItemType.Add(appleItemType, applePrefab);

Where appleitemtype is the type value in the first table for an apple, and the applePrefab is the reference to the apple prefab in Unity. You could do this with the inspector, or just in code.

So, when the server says “Draw an apple”, you know that the apple type is X, and you can just do this:

Instantiate(PrefabsByItemType[X], position, blah blah).

I’ve read up on dictionaries a lot…and they are fast. Not as fast as direct array access, but arrays are not as dynamic to use either. And…this stuff is happening in less than milliseconds. Unless you are picking and dumping BOATLOADS of stuff, a LOT…it may never be an issue. Also…space…is it that big a deal? Let’s say you have 10000 different types of items in your game. If each item type takes up…heck, let’s say 100 bytes. That’s, what…1 meg of memory. On a desktop…your pc won’t even care where it went. Granted, more memory is used for the reference to the variables, but still. Unless you are creating a mobile app, memory for your internal item tracking probably isn’t a big deal.

Anyway…not sure if I answered your questions…any of them :slight_smile: Take it for what it is worth. What you end up having are two tables:
1 for each type of item, and its default values, name, etc
1 for each item you create in the game. Each item knows its item type and owner. You can also store its position, rotation, etc.

When the client connects, the server will need to send it the list of all item types.

Use dictionaries to track things like gameobjects by their item id, create an item of a particular type from a specific prefab, and so forth.
I hope this helps someone. Heck, it may even be correct :slight_smile: