Inventory Systems
Build slot-based inventory with stacking, categories, and drag-drop UI.
Introduction
Inventory systems manage items the player collects. This guide covers slot-based storage, item stacking, categories, equipment, and drag-drop UI.
Guide 17 of 25
Screenshot
Step-by-Step Guide
Define item types
Create an item database with types: weapon, armor, consumable, material, key item. Each has unique properties.
Create inventory slots
Design a grid of slots (e.g., 5x8 = 40 slots). Each slot holds one item type with a count (stackable).
Implement stacking
Stackable items (potions, materials) combine up to max stack (99). Non-stackable items occupy one slot each.
Add drag-drop
Enable dragging items between slots. Swapping, splitting stacks, and merging should all work intuitively.
Implement equipment
Separate equipment slots (head, chest, weapon) that accept only matching types. Equipped items affect stats.
Save inventory state
Serialize the inventory. Store item IDs and counts, not full objects — IDs are lighter and version-safe.
FluxScript Example
Here is a complete FluxScript implementation for this guide:
const MAX_STACK = 99
const SLOT_COUNT = 40
on start {
inventory = { slots: [], equipment: { weapon: null, armor: null } }
for i = 0 to SLOT_COUNT { inventory.slots[i] = null }
items = {
sword: { name: "Iron Sword", type: "weapon", stackable: false, damage: 15 },
potion: { name: "Health Potion", type: "consumable", stackable: true, heal: 50 },
wood: { name: "Wood", type: "material", stackable: true }
}
}
func addItem(itemId, count) {
item = items[itemId]
if item == null return false
if item.stackable {
for i = 0 to SLOT_COUNT {
slot = inventory.slots[i]
if slot != null && slot.itemId == itemId && slot.count < MAX_STACK {
space = MAX_STACK - slot.count
add = math.min(count, space)
slot.count += add
count -= add
if count <= 0 { updateUI(); return true }
}
}
}
for i = 0 to SLOT_COUNT {
if inventory.slots[i] == null {
inventory.slots[i] = { itemId: itemId, count: count }
updateUI()
return true
}
}
ui.toast("Inventory full!")
return false
}
func useItem(slotIndex) {
slot = inventory.slots[slotIndex]
if slot == null return
item = items[slot.itemId]
if item.type == "consumable" {
if slot.itemId == "potion" {
player.heal(item.heal)
effects.spawn("heal_effect", player.position)
}
slot.count -= 1
if slot.count <= 0 inventory.slots[slotIndex] = null
updateUI()
audio.play("use_item")
}
}Node Graph Example
Prefer visual programming? Here is the equivalent Node Graph:
[On Start] --> [Init: 40 empty slots, equipment]
--> [Load: item database]
[Function: addItem] --> [Branch: stackable]
+-- True --> [For Each Slot] --> [Stack: up to MAX_STACK]
--> [Find Empty Slot] --> [Place: itemId + count]
--> [Update UI]
[Function: useItem] --> [Branch: consumable]
--> [Apply Effect: heal/damage/buff]
--> [Remove: 1 from stack] --> [Update UI]Optimization Tips
Keep your implementation fast and efficient with these optimization tips:
- Store item IDs in save data, not full item objects. IDs are lightweight and allow item database updates without breaking saves.
- Pool inventory UI elements. Do not create/destroy UI slot elements when items change — update existing elements.
- Use a centralized updateUI() function. Call it after any inventory change instead of updating UI piecemeal.
- Limit inventory size for game balance. 20-40 slots is typical. Larger inventories are tedious and increase save data.
Common Mistakes
Storing full item objects in save data
Store only item IDs and counts. Full objects bloat save data and break when item stats change.
No inventory full handling
Always check for available space before adding items. Show a notification when there is no room.
