Specialization: Inventory System

What is a specialization?
During our second year at The Game Assembly the students are given the task to create and plan a project of their choice with a topic that they find interesting. I chose to build an inventory system in our student made engine that the student made game studio Water Leaks can use in future game projects.
Goals
My main goal with the inventory system was to create a modular system that Water Leaks (my student game development group) could use in future game projects in order to open up for variability of play styles and increase the replayability of our game projects. Having some kind of inventory was something the group had wanted for previous projects, but hadn't had the time to develop. To decrease the chance of bottle necks between graphics and programming I wanted to create a system where graphic designers could add their inventory items, change visual representation and modify stats independently. I also wanted the items in the inventory to be easily accessible through different sortation methods and give the player an overview of the currently equipped items and active stats.
Process and challenges
Using the UiEditor as basis
During the development process I could use my UiEditor to create the basic layout of the system. This helped me a lot to get a basic visual representation of how the inventory system could look. It sat the baseline for the creation of the inventory system because all the images could easily be replaced without changing anything in the Ui layout and the elements can freely be moved around while retaining the same functionality.

Scroll function and different screen coordinate systems
My first challenge was to make the inventory items appear within the appointed frame and enable scroll to simulate movement of the images and roll through available items. I had to do some rework of our existing systems to convert from pixels to NDC and account for different axis alignment in different parts of the engine, but in the end I managed to use the bounds of a UI element as the clip rect for the inventory items and expanded the UI system to take the bounds into consideration when drawing the sprites.



I ran into some challenges when adding item descriptions as tool tips that would show up during hover. The main challenges was to make them resize dynamically based on how much information should be displayed and to only show up when hovering over the visible part of an inventory item without itself being clipped within the item frame.
A modular item system that’s easy to use
In order to make the inventory items as modular and customizable as possible while at the same time being easy to edit for other disciplines, I had to create a new system for in game. I iterated on this system throughout the development of the project to improve it according to the feedback I received from other programmers and graphic designers. I ended up with a system that could be loaded by the asset manager at game start, accessed freely during runtime, and with as few jsons and json elements as possible. The jsons and item visuals can be changed or added by anyone without a programmer having to manually add additional items with code.
Click to see an example of the Armor items json and how it can be initialized

void InventoryScene::InitializeInventory(){ const InventoryItemSettings armorSettings = AssetRegistry::Get().GetAsset<InventoryItemSettingsAsset>("ISET_Armor")->GetResource(); for (auto& [name, info] : armorSettings.Items) { InitializerLoop(name, _INVENTORY_CATEGORY::CATEGORY_ARMOR); }}void InventoryScene::InitializerLoop(std::string aName, _INVENTORY_CATEGORY aCategory){ switch (aCategory) { case _INVENTORY_CATEGORY::CATEGORY_ARMOR: { std::shared_ptr<ArmorItem> itemCommon = std::make_shared<ArmorItem>(); itemCommon->Init(aName, _INVENTORY_RARITY::RARITY_COMMON); myInventory->AddToInventory(itemCommon); std::shared_ptr<ArmorItem> itemUncommon = std::make_shared<ArmorItem>(); itemUncommon->Init(aName, _INVENTORY_RARITY::RARITY_UNCOMMON); myInventory->AddToInventory(itemUncommon); std::shared_ptr<ArmorItem> itemRare = std::make_shared<ArmorItem>(); itemRare->Init(aName, _INVENTORY_RARITY::RARITY_RARE); myInventory->AddToInventory(itemRare); std::shared_ptr<ArmorItem> itemEpic = std::make_shared<ArmorItem>(); itemEpic->Init(aName, _INVENTORY_RARITY::RARITY_EPIC); myInventory->AddToInventory(itemEpic); std::shared_ptr<ArmorItem> itemLegendary = std::make_shared<ArmorItem>(); itemLegendary->Init(aName, _INVENTORY_RARITY::RARITY_LEGENDARY); myInventory->AddToInventory(itemLegendary); break; } ....
Sorting inventory items
When I play games, I appreciate inventory systems with lots of different ways to sort the items in order to easily find the one I'm looking for. After asking people from different disciplines what kind of sortation they would like in a game I created broad categories and multiple ways to sort items within these categories. On the top row there are symbols for each category: Armor, weapons, accessories, consumables, ingredients and quest items. I also added functionality to switch between categories with the arrows. On the bottom row there are different sortation methods: rarity, weight, sell cost and alphabetical order. These can be displayed in ascending or descending order.

Equipping and unequipping
My main challenge when creating the functionality to equip and unequip items was to accurately reflect this change visually. I had a lot of trouble with items that didn't unequip properly or two handed items not being unequipped from both hands when a new weapon or shield was equipped. I created events that were sent by the items when clicked and handled by the inventory system to reflect the change with a visual representation of the character and updated stats. The stats were easily updated, but for the visual representation I had to do some extra checks to handle two handed weapons.

Trashing and selling
When I added the functionality to sell or trash items, some new bugs was introduced as well. The mayor bug was that when trashing or selling an item that was equipped, the item would be unequipped correctly and stats would be updated, but the visual representation of the character would look as if it still was equipped. I handled this by doing a simple check to see if it was equipped and in that case send out an "unequip this" event and putting the sell/trash event on hold until the item was properly equipped.

End product
The end product is a fully functional and modular inventory system that Water Leaks can use in future game projects. Developers can easily add or modify inventory items and loadouts.
The inventory system features:
- Inventory items divided into different categories.
- A variety of sorting options that sort the items within a category: rarity, weight, sell cost and name.
- Functionality to equip, unequip, sell and trash items
- Visual representation of your equipped items
- Items modifying stats that belong to a player (health, stamina, defence, damage and attack speed)
- Item information showing up when hovering over an item
- A display of the total weight of the items with a visual representation of when you're overencumbered
- A display of money gained from selling items
Future improvements
Some improvements I would like to add are smaller features like visual effects when interacting with an item. I would like to add different effects that are triggered when you sell or trash an item to make this action more visually responsive. I would also like to add a display of the value of an item when you open the sell pop up to show the player how much they would earn by selling.
It would also be fun to do a 3D rendering of the player wearing the equipped items in addition to the item slots. In order to do this I would need some help from graphics to create a 3D model and the inventory item assets, which is why I chose to only display the items as sprites for this project.
If I had more time I would also expand the system to enable consuming consumables that give you a time limited buff and represent this visually with a shader effect on the item.
It would also be cool to expand the system to encompass a way to use the ingredients to upgrade or craft items.