I am currently requiring a module each time a create a certain UI element, as I need to pass through a value, like so
-- Quick write as example
local UI = script:WaitForChild('UI')
local UIClone = UI:Clone()
require(UIClone.UIControl)('Stuff')
UIClone.Parent = PlayerGui
-- UIControl
return function(values)
end
However, I have connections inside that return function, and when the UI gets destroyed it they continue to run. How can I find a work around for this?
I would suggest adding an if statement which checks if the UI is still active. If it is not, it will stop running. Same with the module. If the module is deleted, it won’t continue. I hope I did understand the problem right and addressed it correctly.
Treat ModuleScripts as something you never delete. They are intended to be repositories of commonly used code that are used by multiple scripts, in programming languages, these are called libraries. Place them in e.g. ReplicatedStorage where they can then be required by the client as needed instead of creating/destroying them.
Additionally, when you’re dealing with connections, tie them to variables so you can call Disconnect on them later when you’re done listening to an event:
myConnection = object.Event:Connect(...)
-- later, when you clean up after yourself
myConnection:Disconnect()
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local UI = script:WaitForChild('UI')
local UIClone = UI:Clone()
require(ReplicatedStorage.--[[path to UIControl module]])(UIClone, 'Stuff')
UIClone.Parent = PlayerGui
Your UIControl module in ReplicatedStorage could look like this.
return function(uiClone, values)
local conn1 = someEvent:Connect(someFunct)
local conn2 = anotherEvent:Connect(anotherFunct)
local ancestryConn
ancestryConn = uiClone.AncestryChanged:Connect(function(_, newParent)
if not newParent then
ancestryConn:Disconnect()
conn1:Disconnect()
conn2:Disconnect()
end
end
If you create many connections, you can also store them in a table. The ancestrychanged function can also be created above the return function as long as the variables it needs and doesn’t get from the event are declared before it. If you make a separate variable for every connection, you’ll need to declare all those variables before the function declaration and update them in the function. If you use a table that contains all connections, you only need to declare it before the function.
Another version of UIControl
local allConns = {}
local function ancestryChanged(uiClone, newParent)
if not newParent then
for i, v in ipairs(allConns[uiClone]) do
v:Disconnect()
end
allConns[uiClone] = nil
end
end
local function createConnTable(uiClone)
local conns = {}
allConns[uiClone] = conns
conns[1] = uiClone.AncestryChanged:Connect(ancestryChanged)
return conns
end
return function(uiClone, values)
local conns = createConnTable(uiClone)
conns[2] = someEvent:Connect(someFunct)
conns[3] = anotherEvent:Connect(anotherFunct)
end