So for an inventory I'm creating I need it to update the hot bar you know, to do that I'm using a changed event. The problemo is that if you keep using it it'll start to lag because the events keep stacking up. I need to know how to disconnect events.
(Not the entire script, just parts I think you'll need for context)
function update() print("Prime update") if script.Parent.Image == "" then script.Parent.Amount.Visible = false else if player.Inventory:FindFirstChild(script.Parent.Item.Value)~=nil and player.Inventory[script.Parent.Item.Value].Value == 0 then script.Parent.Amount.Visible = false script.Parent.Image = "" script.Parent.Item.Value = "" elseif player.Inventory:FindFirstChild(script.Parent.Item.Value)~=nil then script.Parent.Amount.Visible = true script.Parent.Amount.Text = "x"..player.Inventory[script.Parent.Item.Value].Value if a~=nil then a = nil end local a = player.Inventory[script.Parent.Item.Value].Changed:connect(update) end end end
[Completed fixed version]
local player = script.Parent.Parent.Parent.Parent.Parent.Parent.Parent local a = nil function onClicked() if script.Parent.Image~="" then if game.Workspace:WaitForChild(player.Name):FindFirstChild(script.Parent.Item.Value)~=nil then game.Workspace:WaitForChild(player.Name).Humanoid:UnequipTools() else game.Workspace:WaitForChild(player.Name).Humanoid:UnequipTools() game.Workspace:WaitForChild(player.Name).Humanoid:EquipTool(game.ReplicatedStorage.assets.Items[script.Parent.Item.Value]:Clone()) end local kids = player.Backpack:GetChildren() for i=1,#kids do if kids[i].ClassName == "Tool" then kids[i]:Destroy() end end elseif script.Parent.Image == "" then game.Workspace:WaitForChild(player.Name).Humanoid:UnequipTools() end end function update() print("Prime update") if script.Parent.Image == "" then script.Parent.Amount.Visible = false if a~=nil then a:disconnect() end else if player.Inventory:FindFirstChild(script.Parent.Item.Value)~=nil and player.Inventory[script.Parent.Item.Value].Value == 0 then script.Parent.Amount.Visible = false script.Parent.Image = "" script.Parent.Item.Value = "" elseif player.Inventory:FindFirstChild(script.Parent.Item.Value)~=nil then script.Parent.Amount.Visible = true script.Parent.Amount.Text = "x"..player.Inventory[script.Parent.Item.Value].Value end end end script.Parent.Item.Changed:connect(function() if a~=nil then a:disconnect() end if script.Parent.Item.Value~="" then a = player.Inventory[script.Parent.Item.Value].Changed:connect(update) end end) userInput = game:GetService("UserInputService") userInput.InputBegan:connect(function(input) if input.UserInputType == Enum.UserInputType.Keyboard and input.UserInputState == Enum.UserInputState.Begin and input.KeyCode == Enum.KeyCode.One then onClicked() end end) game.Players.LocalPlayer.CharacterAdded:connect(function(character) update() end) script.Parent.MouseButton1Click:connect(onClicked) script.Parent.Changed:connect(update) wait(10) update() if player.Inventory:FindFirstChild(script.Parent.Item.Value)~=nil then script.Parent.Amount.Text = "x"..player.Inventory[script.Parent.Item.Value].Value else script.Parent.Amount.Text = "" end
If you're ever in a situation where you're connecting multiple events to the same object within a loop, another event, or multiple times without disconnecting them, you need to fix that immediately. When setting up an event listener, ROBLOX does not overwrite the previous one (as you've probably figured out).
Instead, you need to disconnect the previous event manually if you're going to be throwing it away, or connecting more of the same events to the object. You can do this by using the disconnect method on what your connect
method returns. Here's an example:
-- "PartTouched" now represents what "connect()" returns, which is the event signal for this individual event. local PartTouched = Part.Touched:connect(function() print("Part touched") end) -- Once you have a reference to that signal, you can then disconnect it by calling the "disconnect()" method on it whenever you want. PartTouched:disconnect()
Now, sometimes you only want an event to fire once at a time. You could use a debounce strategy, which is probably better 90% of the time. But for that specific situation where the event must be disconnected right after it fires, this is how it'd be done:
A reference to the event must be defined outside it's callback function
Disconnect the event as soon as it fires
Understanding this, here's an example of how it'd be done:
-- Making the local variable "PartTouched" with a default value of nil. Now we can reference this variable outside our callback function we pass to the event local PartTouched PartTouched = Part.Touched:connect(function() -- We can disconnect it, since we set it to the signal the event returns PartTouched:disconnect() -- The rest of your code print("Hello") end)
While disconnecting events is important if you're going to be using creating more than one for the same object, it can also be unnecessary in avoidable situations. Most of the time, you can just have one event constantly listening for something without needing to mess with disconnect or debounce. In the case of your code, this can be implemented by simply taking your event connection out of your update function, and have it somewhere where it's only going to be created that one time.
Hope that helped, if you have any questions or if anything was unclear, just let me know and I'll get back to you as soon as possible.
Just put something like this in:
myFunction:disconnect()
Substitute 'myFunction' for the name of the function you want to disconnect.