Why is this category "switcher" causing frames to drop?

Hello!

I’m currently working on my inventory system. If an item is added to the player’s data folder, a new ImageButton is created, but if they switch item categories, the ImageButton is parented from nil to the inventory scrolling frame. The problem is that whenever the function to update the inventory is called, it causes a huge lag spike and I am not sure why. Otherwise, it works fine.

Video:

Script:

local function size()
    uiGridLayout.CellSize = UDim2.new(0, scrollingFrame.AbsoluteSize.X / 5, 0,  scrollingFrame.AbsoluteSize.X / 5)
end

runService:BindToRenderStep('InventorySize', Enum.RenderPriority.Last.Value, size) -- This is so the UI maintains the proper size when resizing the screen. I have tried not binding to renderstep and it still causes the same amount of frame drops.

local objects = {}

local categoryFrameHolder = script.Parent.CategoryFrameHolder.CategoryScrollingFrame
for i,v in pairs(categoryFrameHolder:GetChildren()) do
    if v:IsA('Frame') then
        objects[v.Name] = {} -- Create the table with all of the items which are available to the player.
    end
end

local function updateItems()
    for i,v in pairs(scrollingFrame:GetChildren()) do -- Parent all of the currently available ImageButtons to nil
        if v:IsA('Frame') then
            v.Parent = nil
        end
    end
    for i,v in pairs(objects[script.Parent.Category.Value]) do
        v.Parent = scrollingFrame -- Parent all of the items in the new category to the ScrollingFrame
    end
end

script.Parent.Category:GetPropertyChangedSignal('Value'):Connect(updateItems)

inventoryItems.ChildAdded:Connect(function(child) -- When an item's added to the player's inventory
    for i,v in pairs(items:GetDescendants()) do
        if v.Name == child.Name then -- If it's an available item then create the button which should be displayed to the user
            local currentItemTemplate = itemTemplate:Clone()
            local imageButton = currentItemTemplate.ImageButton
            currentItemTemplate.Name = v.Name
            local itemInfo = v:WaitForChild('itemInfo')
            imageButton.Image = 'https://www.roblox.com/asset-thumbnail/image?assetId='..itemInfo:WaitForChild('id').Value..'&width=420&height=420&format=png'
            local itemModel = imageButton.ItemModel
            itemModel.Value = v
            local price = itemInfo:FindFirstChild('price') or itemInfo:FindFirstChild('lowestPrice')
            local rarity, colour = itemHandler:GetRarity(tonumber(price.Value))
            imageButton.Rarity.BackgroundColor3 = colour
            local itemType = itemHandler:GetType(child.Name)
            objects[itemType][#objects[itemType] + 1] = currentItemTemplate
            print(objects)
            updateItems()
            imageButton.MouseButton1Click:Connect(function()
                local handle = v:FindFirstChildWhichIsA('BasePart'):Clone()
                handle.CFrame = CFrame.new(0,0,0)
                handle.Parent = viewportFrame
                if oldObject then
                    oldObject:Destroy()
                end
                oldObject = handle
                itemDescriptionHolder.ScrollingFrame.TextLabel.Text = itemInfo:WaitForChild('description').Value
            end)
        end
    end
end)

Might have to do with the images for everything loading in. I usually had a lot of issues with that on some games.

1 Like

Problem is that images aren’t loaded in each time, they’re loaded in once and then parented to nil. It also happens when using a single ImageLabel. I did try removing the ImageLabel and it did seem to work though. The biggest issue is that I’m not sure how else to display users’ items? Should I create a new ImageLabel every time?

Edit: tried it again with multiple frames, it still causes lag when done with multiple frames, though less than with ImageLabels.

It looks like every time you switch categories, you delete all buttons and make new ones.

Why not just make a ScrollingFrame for each category, and set it to be visible?
You only need to make all others invisible when changing, and the selected frame visible.
You don’t have to create new buttons every time, but only on join.
And it will be much shorter in code.

1 Like

Ever tried putting them into some storage instead of nil and just making them not visible?

o ok it worked
I heard stuff like Instance.new() / Clone() is expensive soo

1 Like