Events inside a loop, inside a function, firing as many times as function is called

Hello devs, im having a problem

local index = {}
local function create(y)
	for n = 1,7 do ---- Creates 7 buttons and sets its position, parent and inserts it into a table called index
		local background = mainScroll.ButtonBackground:Clone()
		local button = mainScroll.CopyButton:Clone()

		background.Position = UDim2.fromScale(addX + seperate, addY + y)
		button.Position = UDim2.fromScale(addX + seperate, addY + y)

		addX += 0.1
		seperate += 0.04

		table.insert(index, button)


		background.Parent = mainScroll
		button.Parent = mainScroll
	end

	for i,button in index do -- makes each button inside index have these events
		print(i,button)
		
		button.MouseButton1Click:Connect(function()

			print("button:",i, button)

			if mouseEnterVal.Value == "Drag_On" then

				secondButton = button
				secondButtonOriginPos = button.Position
				print("calling slot change", secondButton)
				mouseEnterVal.Value = "Normal"

				local goal = {
					Position = secondButton.Position,
					Size = originSize
				}

				local secondGoal = {
					Size = originSize,
					Position = firstButton.Position
				}

				button.ZIndex = 3
				TS:Create(stroke, moveInfo, {Thickness = 0}):Play()
				TS:Create(firstButton, moveInfo, goal):Play()
				TS:Create(secondButton, moveInfo, secondGoal):Play()

				drag.Enabled = false

				task.wait(0.3)
				button.ZIndex = 2
				firstButton.ZIndex = 2
				print("destroyed")
				once = 0

			elseif doubleClick == true and once == 0 then
				doubleClick = false
				textBox.Text = "Double Clicked!"
				mouseEnterVal.Value = "Drag_On"
				enterButton = button
				firstButton = button
				firstButton.ZIndex = 3
				stroke.Parent = firstButton
				TS:Create(stroke, moveInfo, {Thickness = 5}):Play()
				TS:Create(firstButton, moveInfo, {Size = bigSize}):Play()
				firstButtonOriginPos = button.Position

				drag.Enabled = true
				drag.Parent = firstButton
				once += 1
				task.wait(0.8)
				textBox.Text = ""
			end

			task.spawn(function()
				doubleClick = true
				task.wait(0.15)
				doubleClick = false
			end)

			if prevConnection then
				prevConnection:Disconnect()
				prevConnection = nil
			end
			prevConnection = drag.DragEnd:Connect(function()
				if enterButton == nil then
					print("enterButton is nil")
					TS:Create(firstButton, moveInfo, {Position = firstButtonOriginPos}):Play()
				else
					print(enterButton)
					TS:Create(firstButton, moveInfo, {Position = enterButton.Position}):Play()
					TS:Create(enterButton, moveInfo, {Position = firstButtonOriginPos}):Play()
					TS:Create(enterButton, moveInfo, {Size = originSize}):Play()
					TS:Create(stroke, moveInfo, {Thickness = 0}):Play()


					TS:Create(firstButton, moveInfo, {Size = originSize}):Play()
				end
				mouseEnterVal.Value = "Normal"
				drag.Enabled = false
				enterButton = nil
				task.wait(0.3)
				firstButton.ZIndex = 2


				once = 0
			end)

		end)

		button.MouseEnter:Connect(function()
			print("entered")
			local valState = mouseEnterVal.Value
			button.BackgroundColor3 = mouseEnterStatesColor[valState]

			if mouseEnterVal.Value == "Drag_On" then
				enterButton = button
				local sizeUp = TS:Create(enterButton, moveInfo, {Size = bigSize})

				sizeUp:Play()
			end
		end)

		button.MouseLeave:Connect(function()
			button.BackgroundColor3 = mainScroll.CopyButton.BackgroundColor3

			enterButton = nil
			if mouseEnterVal.Value == "Drag_On"  then
				enterButton = button
				local sizeDown = TS:Create(enterButton, moveInfo, {Size = originSize})


				sizeDown:Play()
				enterButton = nil
			end
		end)
	end
end


createButtons.MouseButton1Click:Connect(function() -- Creates buttons
	addX = 0.07
	seperate = 0.01
	create(add)
	add += 0.29
end)

Check video to see how code runs in game and what is the problem (entered print)


Whats happening is, each time i create a new row of buttons, the older row fires one time more, i dont know how to fix it.

When i place for i,v loop outside function, the buttons wont work

Problem is you call create() in an event, and it makes its own events each time its called. You either need to do that somewhere else or use some singleton pattern for events you want at most one of, like this:

local myEvent = nil

...
if myEvent then
    myEvent:Disconnect()
    myEvent = button.MouseEnter:Connect(...)
end
...

The event is disconnected before it is overwritten. The reason you have to do this is events are not disconnected when they are dropped, otherwise the typical method of connecting events, where you don’t put the return value from Connect anywhere, would not work.

doesnt work, makes events fire only on one button. Also if i wanted to use it, shouldnt there be myEvent = nil also?

Try this version

local index = {}
local Connections = {}

local function create(y)

    for i, button in pairs(index) do
        if button.Parent then
            button.Parent = nil 
        end
    end
    
    for i, connection in pairs(Connections) do
        connection:Disconnect()
    end
    
    index = {}
    Connections = {}

	for n = 1,7 do ---- Creates 7 buttons and sets its position, parent and inserts it into a table called index
		local background = mainScroll.ButtonBackground:Clone()
		local button = mainScroll.CopyButton:Clone()

		background.Position = UDim2.fromScale(addX + seperate, addY + y)
		button.Position = UDim2.fromScale(addX + seperate, addY + y)

		addX += 0.1
		seperate += 0.04

		table.insert(index, button)

		background.Parent = mainScroll
		button.Parent = mainScroll
	end

	for i,button in index do -- makes each button inside index have these events
		print(i,button)
		
		table.insert(Connections, button.MouseButton1Click:Connect(function()

			print("button:",i, button)

			if mouseEnterVal.Value == "Drag_On" then

				secondButton = button
				secondButtonOriginPos = button.Position
				print("calling slot change", secondButton)
				mouseEnterVal.Value = "Normal"

				local goal = {
					Position = secondButton.Position,
					Size = originSize
				}

				local secondGoal = {
					Size = originSize,
					Position = firstButton.Position
				}

				button.ZIndex = 3
				TS:Create(stroke, moveInfo, {Thickness = 0}):Play()
				TS:Create(firstButton, moveInfo, goal):Play()
				TS:Create(secondButton, moveInfo, secondGoal):Play()

				drag.Enabled = false

				task.wait(0.3)
				button.ZIndex = 2
				firstButton.ZIndex = 2
				print("destroyed")
				once = 0

			elseif doubleClick == true and once == 0 then
				doubleClick = false
				textBox.Text = "Double Clicked!"
				mouseEnterVal.Value = "Drag_On"
				enterButton = button
				firstButton = button
				firstButton.ZIndex = 3
				stroke.Parent = firstButton
				TS:Create(stroke, moveInfo, {Thickness = 5}):Play()
				TS:Create(firstButton, moveInfo, {Size = bigSize}):Play()
				firstButtonOriginPos = button.Position

				drag.Enabled = true
				drag.Parent = firstButton
				once += 1
				task.wait(0.8)
				textBox.Text = ""
			end

			task.spawn(function()
				doubleClick = true
				task.wait(0.15)
				doubleClick = false
			end)

			if prevConnection then
				prevConnection:Disconnect()
				prevConnection = nil
			end
			prevConnection = drag.DragEnd:Connect(function()
				if enterButton == nil then
					print("enterButton is nil")
					TS:Create(firstButton, moveInfo, {Position = firstButtonOriginPos}):Play()
				else
					print(enterButton)
					TS:Create(firstButton, moveInfo, {Position = enterButton.Position}):Play()
					TS:Create(enterButton, moveInfo, {Position = firstButtonOriginPos}):Play()
					TS:Create(enterButton, moveInfo, {Size = originSize}):Play()
					TS:Create(stroke, moveInfo, {Thickness = 0}):Play()


					TS:Create(firstButton, moveInfo, {Size = originSize}):Play()
				end
				mouseEnterVal.Value = "Normal"
				drag.Enabled = false
				enterButton = nil
				task.wait(0.3)
				firstButton.ZIndex = 2


				once = 0
			end)

		end))

		table.insert(Connections, button.MouseEnter:Connect(function()
			print("entered")
			local valState = mouseEnterVal.Value
			button.BackgroundColor3 = mouseEnterStatesColor[valState]

			if mouseEnterVal.Value == "Drag_On" then
				enterButton = button
				local sizeUp = TS:Create(enterButton, moveInfo, {Size = bigSize})

				sizeUp:Play()
			end
		end))

		table.insert(Connections, button.MouseLeave:Connect(function()
			button.BackgroundColor3 = mainScroll.CopyButton.BackgroundColor3

			enterButton = nil
			if mouseEnterVal.Value == "Drag_On"  then
				enterButton = button
				local sizeDown = TS:Create(enterButton, moveInfo, {Size = originSize})


				sizeDown:Play()
				enterButton = nil
			end
		end))
	end
end


createButtons.MouseButton1Click:Connect(function() -- Creates buttons
	addX = 0.07
	seperate = 0.01
	create(add)
	add += 0.29
end)
1 Like

What was happening is create function was creating 7 buttons and inserting them into a table, after i created buttons again, it inserted 7 new buttons into a table AND 7 old buttons again, so the old row of buttons was running one time more

createButtons.MouseButton1Click:Connect(function() -- Creates buttons
	addX = 0.07
	seperate = 0.01
	create(add)
	add += 0.29
	index = {} ----------- this here fixed everything
end)

FIxed by adding this here

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