Saturday, November 19, 2022

The Inventory System

My Godot achievements are growing, thanks to just how easy it is to do stuff in the Godot game engine.  In just a month's time, I have been able to create a robust inventory system for the game.

Eyesgood's Inventory System

The inventory system is a resource-based system that manages containers and items. It was very important to me that my inventory system could separate mutable properties from immutable ones.  What does that mean?  It simply means the definition resource classes hold all the properties that do not change for the containers and items.  For example, name, description, texture (display image), slot size, max stack size, number of small, medium, and large slots (for containers), weight, length, width, height are all properties that do not change.  They are immutable.  That means I don't have to save these properties in the save game file.  They are static and can reside in a resource file.  However, when I create instances of containers and items, they have properties that do change.  For example, id, parent id, parent slot id, stack amount, UI position (where a container is when locked on the screen), etc.  By taking this approach, the save game file only contains the mutable (changeable) data for each instance of each container and item in the game.  This will reduce loading time, which is something I need when I contemplate a game world of millions of tiles - yes millions!

The UI consists of a single dynamic inventory window that is constructed based on the container's definition.  In the above screenshot, all three windows are the same scene, only they are constructed at runtime from the container definition, which states how many small, medium, and large slots are defined as well as how many columns should be drawn for each slot size.  Since everything is data-driven, I can create an inventory container for every container in the game in any configuration I can imagine.

The Player Inventory window is special in that it has no parent.  But it is a container and therefore has a container definition of two large slots, four medium slots, and twelve small slots.  The backpack fits into a large slot in the player inventory.  Opening it up, it is also a container and is defined containing zero large slots, one medium slot, and six small slots.  Finally, the leather pouch fits into a small slot. But opening it up reveals four small slots.

I wanted to make the inventory system robust but also logical.  A Struggle to Survive is all about working with what you have - which is not very much.  It isn't an MMO where you can hold 50k items in your inventory and run around at full speed.  That's not what I am trying to design.  I want pseudo-realistic design that really forces the player to make decisions just like in a real-life survival scenario. Take the small pouch as an example.  It takes up one small slot in the player's inventory.  Opening it up reveals that it has four small slots for storing small-slot items.  But looking at the player inventory window, we see that a canteen is also a small-slot item.  So is a bear trap.  Does it make sense to put four canteens or four bear traps inside a small leather pouch?  Certainly not!  Therefore, I had to come up with a way to create limitations to the containers that make sense from a pseudo-real-world perspective.  Furthermore, I also wanted to limit just how much a player can carry around.  The solution to these two problems was solved with the concepts of Volume and Weight.

Taking the simple formula of volume = length x width x height, I assigned a volume value to each container.  I also assigned a volume for each item.  The leather pouch has a volume of fifty (5 inches x 2 inches x 5 inches).  When an item is dropped, the volume of the item is compared to the remaining volume of the container.  If there is room, the item will be placed in the container.  If there is not enough room, the item will be rejected and the player will be told the item will not fit inside the container.  Volume allows me to prevent a canteen from being placed inside a pouch.  But it will fit nicely inside a backpack (18 inches x 6 inches x 18 inches).  Since the player inventory is itself a container in this system, I simply set the player inventory to 100 inches x 100 inches x 100 inches, which provides a volume of 1 million - more than enough to handle the slots and volumes of items placed inside.

Weight is currently just used to make sure the player can actually carry what is in the inventory.  The player's strength coupled with a few other attributes will determine how much the player can carry before being hindered from running or even walking.

I am extremely excited to have been able to complete an inventory system for my game.  This is something I struggled with when I was coding the game in UNITY.  But with Godot it was a breeze!  And, having so much community exchanges of ideas and the documentation was extremely helpful.  Permit me to share with you some of the features of this inventory system.

  • Resource-based with game saves only storing mutable data
  • Three slot sizes: small, medium, and large
  • A dictionary-based list of containers and items
  • A single scene for the inventory window, created at runtime based on the container definition
  • Definable slot configurations with column settings
  • Drag-and-drop based on slot size recognition
  • Transfer of items across open containers
  • Item stacking with defined maximum stack limits per item
  • Container volume calculations with checks for remaining volume based on existing container items
  • Recursive volume and weight calculators to get total weight and volume regardless of how many containers are stacked inside other containers
  • Container windows spawn with a tween grow from nothing to max size when opened and reversed when closed, providing a very smooth animation
  • Containers can be positioned anywhere on the screen and locked to prevent accidental movement
  • Container windows can be stacked and will jump to front when clicked
  • Weight can be shown in metric or standard designations to two decimal places
  • Container total weight is shown on each container and includes child container content weights
  • Tool-tips provide instant visibility of container and item name, weight, and volume stats

I haven't decided yet whether I will attempt to create a series of videos showing how to create this system.  It isn't that I want to keep its design to myself.  I am happy to share it.  It is more that creating videos often takes as much or even more time to do than coding the feature the video is about.  We shall see.  In the mean time, thanks for reading along.

Until next time...

No comments:

Post a Comment

Feel free to leave a comment. All comments are moderated.