Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
0

How do you disconnect events? Stacking them is causing major lag

Asked by
ItsMeKlc 235 Moderation Voter
8 years ago
Edited 8 years ago

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)

01function update()
02    print("Prime update")
03    if script.Parent.Image == "" then
04        script.Parent.Amount.Visible = false
05    else
06        if player.Inventory:FindFirstChild(script.Parent.Item.Value)~=nil and  player.Inventory[script.Parent.Item.Value].Value == 0 then
07            script.Parent.Amount.Visible = false
08            script.Parent.Image = ""
09            script.Parent.Item.Value = ""
10        elseif player.Inventory:FindFirstChild(script.Parent.Item.Value)~=nil then
11            script.Parent.Amount.Visible = true
12            script.Parent.Amount.Text = "x"..player.Inventory[script.Parent.Item.Value].Value
13            if a~=nil then
14                a = nil
15            end        
16            local a = player.Inventory[script.Parent.Item.Value].Changed:connect(update)
17        end
18    end
19end

[Completed fixed version]

01local player = script.Parent.Parent.Parent.Parent.Parent.Parent.Parent
02local a = nil
03function onClicked()
04    if script.Parent.Image~="" then
05        if game.Workspace:WaitForChild(player.Name):FindFirstChild(script.Parent.Item.Value)~=nil then
06            game.Workspace:WaitForChild(player.Name).Humanoid:UnequipTools()
07        else
08            game.Workspace:WaitForChild(player.Name).Humanoid:UnequipTools()
09            game.Workspace:WaitForChild(player.Name).Humanoid:EquipTool(game.ReplicatedStorage.assets.Items[script.Parent.Item.Value]:Clone())
10        end
11        local kids = player.Backpack:GetChildren()
12        for i=1,#kids do
13            if kids[i].ClassName == "Tool" then
14                kids[i]:Destroy()
15            end
View all 72 lines...

2 answers

Log in to vote
2
Answered by 8 years ago
Edited 8 years ago

You never need more than one event for the same job


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:

1-- "PartTouched" now represents what "connect()" returns, which is the event signal for this individual event.
2local PartTouched = Part.Touched:connect(function()
3    print("Part touched")
4end)
5 
6-- Once you have a reference to that signal, you can then disconnect it by calling the "disconnect()" method on it whenever you want.
7PartTouched:disconnect()

Only firing once

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

    • You could avoid doing this by using a global variable (i.e, a non-local variable), but that's not good practice. What you should do, is define a local variable with no value to tell the script you're going to assign something to it later.
  • Disconnect the event as soon as it fires

    • In case something might fire your event twice immediately and your code yields at some point before disconnecting the event, you should always disconnect it before doing anything else.

Understanding this, here's an example of how it'd be done:

01-- 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
02local PartTouched
03 
04PartTouched = Part.Touched:connect(function()
05    -- We can disconnect it, since we set it to the signal the event returns
06    PartTouched:disconnect()
07 
08    -- The rest of your code
09    print("Hello")
10end)

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.

0
The reason why I'm doing it this way is because the item there changes and I don't want it to go through all 100+ items in my game just to get this one thing. I tried putting a:disconnect() on line 14 but it didn't work. Am I using it incorrectly? ItsMeKlc 235 — 8y
Ad
Log in to vote
-3
Answered by 8 years ago

Just put something like this in:

1myFunction:disconnect()

Substitute 'myFunction' for the name of the function you want to disconnect.

0
You don't disconnect the function, you disconnect the signal the connect method returns. ScriptGuider 5640 — 8y
0
I put 'a:disconnect()' on line 14 and it didn't help ItsMeKlc 235 — 8y

Answer this question