game design is hard, not because any given thing is “hard” perse (some things are hard, but most are just a bunch of relatively simple steps), the real “hard part” has to do with what seems like a “simple” decision is actually 30 knock-on-effect decisions in a trench-coat. for more details on this you can look at “Game Design” + “The Door Problem”, “The Ladder Problem”, or “The Stairs Problem”; although these are more or less examples.
the biggest issues with an inventory itself (it can just be an array of structs UObjects at the worst, but most games don’t need to go beyond an Array of Structs, an Actor is way to heavy, and creates a lot of headaches especially if there are loading transitions), but the actions an inventory needs to do, and the questions attached to it:
- is the number of items to be held known? (or at least the maximum)
- are any of the items not unique (this mostly applies to like point and click adventures, but can be usable for things like KeyItems, as you might not need an “item” specifically but just a “bitflag”)
- can items be stacked?
- can items be manually moved by the user? does the order matter?
- do items have a condition, durability?
-
- can items with similar condition, durability be stacked?
- can Items be dropped/discarded?
- if items can be dropped/discarded can this put the game in a soft-lock state? Is that OK?
- if Items can be dropped/discarded/sold can only one item be done at a time, or multiple at once?
- can items be lost in some other way?
- are items added to the inventory in batches, or one at a time? can multiple of the same item be added at once?
- …
depending on how hard you want to go into “Single Responsibility Principle” and interfaces is effectively your difficulty selection for the feature, and as a “Beginner/Intermediate” developer (do not constrain your abilities to your programming language, and yes Blueprints is programming you just get boxes, and lines instead of structured English and those random symbols on the keyboard).
a tangled mess means that you have a deeply integrated system, and that isn’t a bad thing, heck a deeply integrated system is less “reusable”, but also easier to reason about because you don’t have to jump between multiple elevations of abstraction to follow a function chain, and get to the goal, especially when you are starting out/learning.
If you are talking about how “tangled” your lines of spaghetti are in the blueprint graph, that is a “feature” of the language, and why you can hover over a pin to see where the line on the graph goes, or put comments in the graph as breadcrumbs for your future self
Comments are for helping other team members understand what a thing is doing, and whether you’re on a large team, or working by yourself the “other team member” is likely to be yourself 6 weeks from now.
a “basic” inventory system (with minimal prescriptions) :
- a component class for the inventory itself.
-
- is a component so it can be owned by an actor.
-
- has an array of “itemStruct”, or UObject, you will need at least “add(Item)”, “remove(Item)”, “check(Item)”, “Use(Item)”, and maybe a “merge(Inventory)”
- an actor class for the items that exist in the world, and maybe for the item as it exists being held.
-
- will probably also have its own inventory, though if you go with interfaces then the actor might be the inventory
- a DataTable, or collection of DataAssets that are the detailed definition of the items
the bare minimume for the struct or UObject (struct if you want a unified what an item does in some manager, the inventory itself, or on the thing that “uses” the item, but UObject allows for the item to have scripting on itself)
- itemID: this could even be just an integer; instead of “Thor’s Mighty Lightning Axe” it can be just “15”, and then in the DataTable the rowName can be 15, and then the DataTable has a member with the “DisplayText”, for DataAsset it would be “Item_15”.
- the other stuff that is needed for a specific item in the inventory.
a more advanced “cute” implementation if items cannot stack then the Inventory could just be an Array of Integers (the “ItemID”), or for items that can stack a TMap<Int ItemID, int Quantity>, then your dataTable, or collection of DataAsset would have all the details. again this a a more advanced, and needs to be weighed heavily against quantity and frequency of lookups.
the bigger the amount of information in the struct or UObject for the item in the Inventory the more on hand the data is when you need it saving a lookup, while the opposite will lead to “slower” lookups, but the Inventory and the array has a lot less duplicated data with a smaller memory footprint as they are running around the world which could help in other ways