How could I make a "dynamic" inventory?

The title might sound confusing, but let me explain: I’m developing an inventory system, and I’ve almost finished everything, except for one thing — the inventory itself. I had a few ideas, but one of them caught my attention the most: using UIPageLayout to display items and navigate through the inventory. However, I ran into a problem (honestly, it’s nothing too serious, but it’s a bit annoying). In my current system, each page has a limit of 12 items. If it exceeds that, a new page is created, and the new items are directed there, and so on.

Here’s where the “dynamic” part I mentioned in the title comes in: what happens when the player deletes an item?

Suppose a player deletes an item on the first page of the inventory. This page would then have 11 items, right? That’s the issue. Even though it doesn’t ruin the user experience, it could become bothersome in the long run. The way I envisioned it is as follows: in this case, if the player deletes an item on any page other than the last one, items from subsequent pages would shift to fill the gap.

I know, this might sound a bit strange if you’re not visualizing what’s happening (unfortunately, I can’t take a screenshot at the moment of writing this), but think of a stack of blocks arranged vertically. If you remove a block from the middle, the blocks above it would fall down. My system works kind of like that, except horizontally.

Does anyone have any opinions about using UIPageLayout for an inventory system? I decided to use it mainly because, as far as I understand, it doesn’t render pages that aren’t visible, which should help with performance (I hope). I’d also like to know how you would design this inventory if you were in my place. I have some ideas for how to approach this, but I don’t feel like they’re good enough.

1 Like

I hope you didnt manually make each slot and page :grimacing: :grimacing: :grimacing:

there should simply be one sample slot and you clone it for how ever many items you have. This function should be called updateInv. I havent worked with ui page, but i have with ui grid. But if im not mistaken, it should format how you want it to even with ui page

So every time an item is changed, you would want to call this update function. So this way it would add only as many as you need.

1 Like

you could either let players create new pages to sort their items easier (kind of like a phone homescreen) or you could just recursively move the an item from the next page into the previous page (item from page 2 goes to page 1, item from page 3 goes to page 2 → page 3 has 11 items instead)

it looks like you want the second option

that means you’d just need to handle items being shifted in a page and items being moved from one page to another

move an item in-page → shift page (only shift items if it is last page)
move an item to another page → shift items + shift page(s)
delete an item → shift page(s)

this is a good way to think of it. all you would need to do is use the slot and page index that’s being changed

you don’t really need UIPageLayout for this (i’ve never used it for any page system)
i would create my own version of this just to show you how you could do it, but i’m hungry

but here’s how you could shift the items after removing something

-- Inventory is an array of Pages
-- Pages are arrays of slots
local Inventory = {
  [1] = {"Apple", "Banana", "Cheese"};
  [2] = {"Grape", "Watermelon", "Carrot"};
  [3] = {"Tomato", "Cucumber", "Lettuce"};
}

local function FindItem(TargetItem: string): {["PageIndex"]: number, ["SlotIndex"]: number, ["Item"]: number} | {}
  for PageIndex, Page in Inventory do
    for SlotIndex, Item in Page do
      if Item ~= TargetItem then continue end

      return {
        ["PageIndex"] = PageIndex;
        ["SlotIndex"] = SlotIndex;
        ["Item"] = Item;
      }
    end
  end

  return {}
end

local function ShiftInventoryPage(PageIndex: number, SlotIndex: number)
  local CurrentPage = Inventory[PageIndex]
  local NextPage = Inventory[PageIndex + 1]
  local NextPageFirstItem = NextPage and NextPage[1] or false

  for i = SlotIndex, #CurrentPage - 1 do
    CurrentPage[i] = CurrentPage[i + 1]
  end

  CurrentPage[#CurrentPage] = NextPageFirstItem

  if NextPage then 
    NextPage[1] = CurrentPage[#CurrentPage]
    ShiftInventoryPage(PageIndex + 1, 1)
  end
end

local function RemoveItem(Item: string)
  -- Find the item, remove the item, shift the inventory if nessecary
  local FoundItem = FindItem(Item)
  if not FoundItem then warn(`Attempted to remove missing item '{Item}' from inventory`) return end
  Inventory[FoundItem.PageIndex][FoundItem.SlotIndex] = false

  -- Return if the item is in the last slot of the last page
  if FoundItem.Item == Inventory[#Inventory][#Inventory[#Inventory]] then return end -- Ignore how ugly this is
  ShiftInventoryPage(FoundItem.PageIndex, FoundItem.SlotIndex)
end

RemoveItem("Carrot")
print(Inventory)

--[[
  Output:

  Page 1: Apple, Banana, Cheese
  Page 2: Grape, Watermelon, Tomato
  Page 3: Cucumber, Lettuce, false
]]

edit: i didn’t think to create AddItem and MoveItem functions (i’m gonna get some food). let me know if you need help with that

1 Like