Designing a data-driven inventory system in UMG: item types, equip slots, world-space previews, and the separation between inventory data and UI presentation.
This project is an inventory system prototype built entirely in Blueprints with Unreal Engine 5.4, inspired by the item management style of The Legend of Zelda series. It was developed following this Udemy course as a focused study of how to design an inventory that handles multiple item categories, equip states, and rich item metadata — both in the world and inside the UI.
You can watch the prototype in action here: YouTube
Item Data Model
The foundation of any inventory system is its data model — the structure that describes what an item is before deciding how it’s displayed or how it behaves. In this prototype, items carry a consistent set of metadata: type, name, description, and a visual representation. This information is available both when the item is in the world (displayed before pickup) and when it’s in the inventory (displayed in the UI), which means the data needs to exist independently of whichever context is rendering it.
Using Data Tables in Unreal to store item definitions is the correct approach here: each row defines one item type, and both the world actor and the inventory widget read from the same row to populate their respective displays. This avoids duplicating item data across two different places and ensures consistency — if an item’s description changes, it changes everywhere.
The three item categories — swords, shields, and eatables — share the common metadata but differ in what happens when they’re used. This is the key design decision: how much of the behavior difference is encoded in the data, and how much requires different code paths.
Item Type Behavior: Equip vs. Consume
Swords and shields are equipment: selecting them in the inventory equips them to a slot on the character, visually attaching the mesh and enabling associated gameplay behavior. Eatables are consumables: using them removes them from the inventory and applies an effect — restoring hearts in this case.
The cleanest way to handle this distinction is through the item type field itself, which drives a branch in the “use item” logic. The inventory doesn’t need separate systems for equippable and consumable items — it needs one use action that reads the item type and dispatches to the appropriate handler. This keeps the inventory code unified even as item behavior varies.
Equipping introduces a secondary consideration: slot management. The character has a sword slot and a shield slot. Equipping a new sword when one is already equipped means either replacing the previous one (returning it to inventory) or blocking the action. The prototype implements replacement — the previously equipped item returns to the inventory, which avoids item loss and keeps the inventory state consistent.
World-Space Item Information
One of the distinguishing features of this prototype is that item metadata is visible before pickup — approaching an item in the world displays its name, type, and description. This requires the world item actor to present UI without being part of the inventory system yet.
The implementation uses a Widget Component attached to the world item actor, rendering a small info panel in world space that faces the camera. The widget reads from the same item data row as the inventory UI. When the player picks up the item, the world actor is destroyed and the item data is transferred to the inventory — the same data structure moving from one context (world presentation) to another (inventory management).
This continuity of data across contexts is what makes the system feel coherent: the player sees the same name and description on the ground as they do in their inventory.
Health System: Hearts
The health system uses a heart-based display — a visual pattern made famous by The Legend of Zelda — where health is represented as a sequence of heart icons that fill and empty rather than a numeric value or a bar. This is a presentational choice with a data implication: the underlying health value needs to map cleanly to a number of whole and half hearts, which means health is effectively quantized into discrete units.
The heart display widget iterates over the health value and renders each heart as full, half, or empty accordingly. Consuming an eatable item increases the health value and the widget updates reactively. The hearts pattern is also a good UMG exercise because it requires dynamically generating a variable number of widget instances at runtime rather than having a fixed layout.
Crystal Collection
The crystal collectibles function as a secondary resource counter — a simpler system than the inventory, with no type distinction or equip logic. Crystals increment a counter when collected, and the UI displays the current count. They serve as a good contrast to the main inventory: not everything in a game needs the full complexity of a typed, slotted item system. Recognizing when a simpler counter is the right tool — rather than routing everything through the inventory — is an important design judgment.
Reflection
Inventory systems are deceptively complex because they sit at the intersection of data management, UI architecture, and gameplay logic. The Zelda-like framing keeps the scope focused — three item types, two equip slots, one consumable effect — but within that scope, every design decision has clear implications: how items are defined, how the data flows from world to UI, how equipping interacts with slot state.
In C++, this system would be a natural fit for a UInventoryComponent holding an array of FItemData structs defined in a UDataTable, with UUserWidget subclasses binding to the component via delegates. The Blueprint version maps directly to that structure — the wiring is just more visual.
Leave a comment