Function firing multiple times

Im making an inventory system but when i equip my item it equips that item for how many items i have so if i equip a hat and have 10 items in my inventory it would equip 10 hats on my head

Server

local Players = game:GetService('Players')
local player = Players.LocalPlayer
local char = player.Character or player.CharacterAdded
local humanoid = char:WaitForChild('Humanoid')
local MS = game:GetService('MarketplaceService')
local ReplicatedStorage = game:GetService('ReplicatedStorage')
local values = ReplicatedStorage:WaitForChild('SendValues')
local Gradients = ReplicatedStorage:WaitForChild('Gradients')
local info = ReplicatedStorage:WaitForChild('Info')

local inventoryFolder = player:WaitForChild(player.Name .. " Inventory")
local temp = script.Parent.ScrollingFrame.Temp
local InventoryTab = script.Parent.Parent.InventoryTab
local equipButton = InventoryTab:WaitForChild('Equip')
local unequipButton = InventoryTab:WaitForChild('Unequip')

local equippedItems =  {}

local onclick = ReplicatedStorage:WaitForChild('Onclick')
local LoadAsset = ReplicatedStorage:WaitForChild('LoadAsset')
local CurrentSelectedItem = nil




local function EquipDisplay(itemAssetId, name, default, equippedF)
	local debounce = false

	local function updateButtonVisibility(isEquipped)
		default.Visible = not isEquipped
		equippedF.Visible = isEquipped
		equipButton.Visible = not isEquipped
		unequipButton.Visible = isEquipped
	end

	local function toggleEquippedStatus()
		if debounce then
			return  
		end

		debounce = true 

		local isEquipped = itemAssetId.Equipped.Value
		local newEquipped = not isEquipped

		if newEquipped and #equippedItems >= 4 then
			debounce = false 
			return  
		end

		equippedItems[tostring(itemAssetId)] = newEquipped

		itemAssetId.Equipped.Value = newEquipped

		updateButtonVisibility(newEquipped)

		if not newEquipped then
			equippedItems[tostring(itemAssetId)] = false
			itemAssetId.Equipped.Value = false
		end

		task.wait(.5)
		debounce = false

		LoadAsset:FireServer(name, itemAssetId.Equipped.Value)

	end

	equipButton.MouseButton1Click:Connect(toggleEquippedStatus)
	unequipButton.MouseButton1Click:Connect(toggleEquippedStatus)

end



ReplicatedStorage.RemoteEvent.OnClientEvent:Connect(function(itemAssetId, rap)
	local limitedItem = Instance.new('StringValue')
	limitedItem.Name = tostring(itemAssetId)
	limitedItem.Value = rap
	limitedItem.Parent = inventoryFolder

	local equipped = Instance.new('BoolValue')
	equipped.Name = "Equipped"
	equipped.Value = false
	equipped.Parent = limitedItem
	end)
local function updateInventoryDisplay()
	for _, existingItem in ipairs(temp.Parent:GetChildren()) do
		if existingItem:IsA("ImageButton") and existingItem.Name ~= "Temp" then
			existingItem:Destroy()
		end
	end
	


	
	for _, item in ipairs(inventoryFolder:GetChildren()) do

		if item:IsA("StringValue") then
			local itemAssetId = tonumber(item.Name)
			local productInfo = MS:GetProductInfo(itemAssetId)
	
			if productInfo then
				local itemClone = temp:Clone()
				local default = itemClone:WaitForChild('Default')
				local Equipped = itemClone:WaitForChild('Equipped')
				info.OnClientEvent:Connect(function(receivedEquippedItems)
					local itemInfo = receivedEquippedItems[tostring(itemAssetId)]
					if default:FindFirstChild('Rarity') then
					default:WaitForChild('Rarity').Text = itemInfo.Rarity
					local gradientClone = Gradients:FindFirstChild(itemInfo.Rarity):Clone()
					gradientClone.Enabled = true
					gradientClone.Parent = default

					Equipped:WaitForChild('Rarity').Text = itemInfo.Rarity
					local gradientClone = Gradients:FindFirstChild(itemInfo.Rarity):Clone()
					gradientClone.Enabled = true
					gradientClone.Parent = Equipped
					end
				end)
				itemClone.Visible = true
				itemClone.Name = productInfo.Name
				itemClone.Parent = temp.Parent
				default:WaitForChild('LimitedImg').Image = "rbxthumb://type=Asset&id=" .. itemAssetId .. "&w=420&h=420"
				default:WaitForChild('LimitedName').Text = productInfo.Name
				Equipped:WaitForChild('LimitedImg').Image = "rbxthumb://type=Asset&id=" .. itemAssetId .. "&w=420&h=420"
				Equipped:WaitForChild('LimitedName').Text = productInfo.Name

				itemClone.MouseEnter:Connect(function()
					local stroke = default:FindFirstChildOfClass("UIStroke")
					if not stroke then
						stroke = Instance.new('UIStroke')
						stroke.Color = Color3.new(1, 1, 1)
						stroke.Thickness = 2
						stroke.ApplyStrokeMode = Enum.ApplyStrokeMode.Border
						stroke.Parent = default
					else
						stroke.Enabled = true
					end
				end)
			

				itemClone.MouseLeave:Connect(function()
					local stroke = default:FindFirstChildOfClass("UIStroke")
					if stroke then
						stroke.Enabled = false
					end
				end)





				itemClone.MouseButton1Down:Connect(function()
					onclick:FireServer()
					CurrentSelectedItem =itemAssetId
					print(CurrentSelectedItem)
					InventoryTab.LimitedName.Text = productInfo.Name
					InventoryTab.LimitedId.Text = "#" .. itemAssetId
					InventoryTab.LimitedImg.Image = "rbxthumb://type=Asset&id=" .. itemAssetId .. "&w=420&h=420"
					InventoryTab.Rap.Text = "RAP: " .. item.Value
					
					
					values.OnClientEvent:Connect(function(receivedEquippedItems)
						local itemInfo = receivedEquippedItems[tostring(CurrentSelectedItem)]
						if itemInfo then
							InventoryTab.Rarity.Text = itemInfo.Rarity
							InventoryTab.Rarity.BackgroundColor3 = itemInfo.Color
							InventoryTab.DefaultValue.Text = "Default Value: " .. itemInfo.Default
						end
					end)
					

						EquipDisplay(item, CurrentSelectedItem, default, Equipped)
				end)
			end
		end
	end
end



updateInventoryDisplay()


inventoryFolder.ChildAdded:Connect(updateInventoryDisplay)
inventoryFolder.ChildRemoved:Connect(updateInventoryDisplay)

Its the EquipDisplay function

I recommend avoiding this type of structure because it causes what’s called a memory leak,
you can learn about memory leaks here
Once you check what that is, you’ll eventually find out why your code was being executed more than expected, then you can rewrite it in a safer structure.

Hope this helps!

Like @capsori said, this kind of structure causes memory leaks. I’ll just write a shorter explanation.

The issue is making connections inside of connections - each time the outer connection is run, new connections for the inside are created - you end up with multiple connections for the same thing. Some fixes:

  • Using :Once for the inside connections
  • Disconnecting connections when they are no longer needed
  • Moving inside connections outside of other connections (this is probably the best)
1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.