Debounce for Setting Toggling not Working in a Settings GUI, How do I Implement it Properly?

  1. What do you want to achieve?
    I am making a settings GUI in which you can toggle settings on or off. I want to add a small delay for toggling on or off settings by adding a debounce. The debounce works like this, there is a table called DebouncedSettings which contains the settings as strings which can not be toggled on or off momentarily. If you try to toggle a setting while it’s inside the DebouncedSettings table it won’t let you. If it’s not inside the DebouncedSettings table, then it will let you. Clicking the toggle button of a setting adds that setting to the table.

  2. What is the issue?
    Each time I have tried to code this in the way I just described I failed to implement it properly. Either the debounce runs when it shouldn’t or other weird things happen such as not being able to toggle the setting at all. I find it working hard with tables at times.

  3. What solutions have you tried so far?
    I have searched for similar posts to what I’m after to make on the devforum but I didn’t find anything that helped me. I tried fixing it for hours with loops and if statements but it still wasn’t right. If anyone could tell me how to implement this that would be greatly appreciated!

My code is inside a GUI as a client script. Here is my code with some comments explaining parts of the code and where the debounce should start and end:

local Players = game:GetService("Players")
local Player = Players.LocalPlayer
local TweenService = game:GetService("TweenService")
local CurrentSong = game:GetService("ReplicatedStorage"):WaitForChild("Other"):WaitForChild("CurrentSong")
local StarterGui = game:GetService("StarterGui")
local Gui = script.Parent
local SettingsFrame = Gui:WaitForChild("Backround"):WaitForChild("Settings")
local CurrentSongText = Gui:WaitForChild("Backround"):WaitForChild("CurrentSong")

local AFKModeSetting = SettingsFrame:WaitForChild("AFK Mode")
local VIPTrailSetting = SettingsFrame:WaitForChild("VIP Trail")
local GameMusicSetting = SettingsFrame:WaitForChild("Game Music")
local PartyMusicSetting = SettingsFrame:WaitForChild("Party Music")
local ShadowsSetting = SettingsFrame:WaitForChild("Shadows")
local TransitionsSetting = SettingsFrame:WaitForChild("Transitions")

local AFKModeSettingToggleClick = AFKModeSetting:WaitForChild("Frame"):WaitForChild("ToggleClick")
local VIPTrailSettingToggleClick = VIPTrailSetting:WaitForChild("Frame"):WaitForChild("ToggleClick")
local GameMusicSettingToggleClick = GameMusicSetting:WaitForChild("Frame"):WaitForChild("ToggleClick")
local PartyMusicSettingToggleClick = PartyMusicSetting:WaitForChild("Frame"):WaitForChild("ToggleClick")
local ShadowsSettingToggleClick = ShadowsSetting:WaitForChild("Frame"):WaitForChild("ToggleClick")
local TransitionsSettingToggleClick = TransitionsSetting:WaitForChild("Frame"):WaitForChild("ToggleClick")

local AFKModeSettingToggleFrame = AFKModeSettingToggleClick:WaitForChild("ToggleFrame")
local VIPTrailSettingToggleFrame = VIPTrailSettingToggleClick:WaitForChild("ToggleFrame")
local GameMusicSettingToggleFrame = GameMusicSettingToggleClick:WaitForChild("ToggleFrame")
local PartyMusicSettingToggleFrame = PartyMusicSettingToggleClick:WaitForChild("ToggleFrame")
local ShadowsSettingToggleFrame = ShadowsSettingToggleClick:WaitForChild("ToggleFrame")
local TransitionsSettingToggleFrame = TransitionsSettingToggleClick:WaitForChild("ToggleFrame")

local AFKModeSettingToggleStatus = AFKModeSettingToggleClick:WaitForChild("ToggleStatus")
local VIPTrailSettingToggleStatus = VIPTrailSettingToggleClick:WaitForChild("ToggleStatus")
local GameMusicSettingToggleStatus = GameMusicSettingToggleClick:WaitForChild("ToggleStatus")
local PartyMusicSettingToggleStatus = PartyMusicSettingToggleClick:WaitForChild("ToggleStatus")
local ShadowsSettingToggleStatus = ShadowsSettingToggleClick:WaitForChild("ToggleStatus")
local TransitionsSettingToggleStatus = TransitionsSettingToggleClick:WaitForChild("ToggleStatus")

local TweenInfo1 = TweenInfo.new(
	0.2,
	Enum.EasingStyle.Linear,
	Enum.EasingDirection.InOut,
	0,
	false,
	0
)

-- The table in which settings you can not toggle on or off are stored.
local DebouncedSettings = {}

-- The function that runs when the toggle button is pressed.
local function ToggleToggleFrameAppearance(ToggleFrame, TrueOrFalse, IsServerRequest)
	if ToggleFrame == nil then return end
	if TrueOrFalse == nil then return end

-- This is the setting name, it will always be a string.
	local SettingName = ToggleFrame.Parent.Parent.Parent.Name
-- The rest here is just for animation purposes.
	local ToggleDot = ToggleFrame:WaitForChild("ToggleDot")
	local Tween = TweenService:Create(ToggleFrame, TweenInfo1, {BackgroundColor3 = Color3.fromRGB(255, 0, 0)})
	local Tween2 = TweenService:Create(ToggleFrame, TweenInfo1, {BackgroundColor3 = Color3.fromRGB(0, 255, 0)})
	local Tween3 = TweenService:Create(ToggleDot, TweenInfo1, {Position = UDim2.new(0.2, 0,0.5, 0)})
	local Tween4 = TweenService:Create(ToggleDot, TweenInfo1, {Position = UDim2.new(0.8, 0,0.5, 0)})

-- This is just if I need to instantly toggle a setting on or off from the server, this doesn't need to be in a debounce.
	if IsServerRequest ~= nil and IsServerRequest == true then
		if TrueOrFalse == true then
			Tween2:Play()
			Tween4:Play()
		else
			Tween:Play()
			Tween3:Play()
		end
	else
-- So here is where it should be checked if the setting is in the table, and if its not put it inside the table and it shouldn't be allowed to be toggled off or on momentarily.
-- The TrueOrFalse variable just tells the code whether or not to enable a setting. True means to enable it while false means to disable it.
		if TrueOrFalse == true then
			Tween2:Play()
			Tween4:Play()
			Tween4.Completed:Wait()
			wait(0.1)
			-- The setting should be allowed to be toggled now so remove it from the table.
		else
			Tween:Play()
			Tween3:Play()
			Tween3.Completed:Wait()
			wait(0.1)
			-- The setting should be allowed to be toggled now so remove it from the table.
		end
	end
end

-- This is something else not needed to be touched.
local function UpdateCurrentSongText()
	CurrentSongText.Text = "Current Song: " .. CurrentSong.Value
end

UpdateCurrentSongText()

-- This here triggers the toggling of the setting if a button is clicked. Toggle status just has the default value of whether or not a setting is enabled. It is a boolean value.
AFKModeSettingToggleClick.MouseButton1Down:Connect(function()
	AFKModeSettingToggleStatus.Value = not AFKModeSettingToggleStatus.Value
end)

VIPTrailSettingToggleClick.MouseButton1Down:Connect(function()
	VIPTrailSettingToggleStatus.Value = not VIPTrailSettingToggleStatus.Value
end)

GameMusicSettingToggleClick.MouseButton1Down:Connect(function()
	GameMusicSettingToggleStatus.Value = not GameMusicSettingToggleStatus.Value
end)

PartyMusicSettingToggleClick.MouseButton1Down:Connect(function()
	PartyMusicSettingToggleStatus.Value = not PartyMusicSettingToggleStatus.Value
end)

ShadowsSettingToggleClick.MouseButton1Down:Connect(function()
	ShadowsSettingToggleStatus.Value = not ShadowsSettingToggleStatus.Value
end)

TransitionsSettingToggleClick.MouseButton1Down:Connect(function()
	TransitionsSettingToggleStatus.Value = not TransitionsSettingToggleStatus.Value
end)

AFKModeSettingToggleStatus.Changed:Connect(function()
	ToggleToggleFrameAppearance(AFKModeSettingToggleFrame, AFKModeSettingToggleStatus.Value)
end)

VIPTrailSettingToggleStatus.Changed:Connect(function()
	ToggleToggleFrameAppearance(VIPTrailSettingToggleFrame, VIPTrailSettingToggleStatus.Value)
end)

GameMusicSettingToggleStatus.Changed:Connect(function()
	ToggleToggleFrameAppearance(GameMusicSettingToggleFrame, GameMusicSettingToggleStatus.Value)
end)

PartyMusicSettingToggleStatus.Changed:Connect(function()
	ToggleToggleFrameAppearance(PartyMusicSettingToggleFrame, PartyMusicSettingToggleStatus.Value)
end)

ShadowsSettingToggleStatus.Changed:Connect(function()
	ToggleToggleFrameAppearance(ShadowsSettingToggleFrame, ShadowsSettingToggleStatus.Value)
end)

TransitionsSettingToggleStatus.Changed:Connect(function()
	ToggleToggleFrameAppearance(TransitionsSettingToggleFrame, TransitionsSettingToggleStatus.Value)
end)

-- This is something else not needed to be touched.
CurrentSong.Changed:Connect(function()
	UpdateCurrentSongText()
end)
1 Like
local Players = game:GetService("Players")
local Player = Players.LocalPlayer
local TweenService = game:GetService("TweenService")
local CurrentSong = game:GetService("ReplicatedStorage"):WaitForChild("Other"):WaitForChild("CurrentSong")
local StarterGui = game:GetService("StarterGui")
local Gui = script.Parent
local SettingsFrame = Gui:WaitForChild("Backround"):WaitForChild("Settings")
local CurrentSongText = Gui:WaitForChild("Backround"):WaitForChild("CurrentSong")
local Debounce = false

local AFKModeSetting = SettingsFrame:WaitForChild("AFK Mode")
local VIPTrailSetting = SettingsFrame:WaitForChild("VIP Trail")
local GameMusicSetting = SettingsFrame:WaitForChild("Game Music")
local PartyMusicSetting = SettingsFrame:WaitForChild("Party Music")
local ShadowsSetting = SettingsFrame:WaitForChild("Shadows")
local TransitionsSetting = SettingsFrame:WaitForChild("Transitions")

local AFKModeSettingToggleClick = AFKModeSetting:WaitForChild("Frame"):WaitForChild("ToggleClick")
local VIPTrailSettingToggleClick = VIPTrailSetting:WaitForChild("Frame"):WaitForChild("ToggleClick")
local GameMusicSettingToggleClick = GameMusicSetting:WaitForChild("Frame"):WaitForChild("ToggleClick")
local PartyMusicSettingToggleClick = PartyMusicSetting:WaitForChild("Frame"):WaitForChild("ToggleClick")
local ShadowsSettingToggleClick = ShadowsSetting:WaitForChild("Frame"):WaitForChild("ToggleClick")
local TransitionsSettingToggleClick = TransitionsSetting:WaitForChild("Frame"):WaitForChild("ToggleClick")

local AFKModeSettingToggleFrame = AFKModeSettingToggleClick:WaitForChild("ToggleFrame")
local VIPTrailSettingToggleFrame = VIPTrailSettingToggleClick:WaitForChild("ToggleFrame")
local GameMusicSettingToggleFrame = GameMusicSettingToggleClick:WaitForChild("ToggleFrame")
local PartyMusicSettingToggleFrame = PartyMusicSettingToggleClick:WaitForChild("ToggleFrame")
local ShadowsSettingToggleFrame = ShadowsSettingToggleClick:WaitForChild("ToggleFrame")
local TransitionsSettingToggleFrame = TransitionsSettingToggleClick:WaitForChild("ToggleFrame")

local AFKModeSettingToggleStatus = AFKModeSettingToggleClick:WaitForChild("ToggleStatus")
local VIPTrailSettingToggleStatus = VIPTrailSettingToggleClick:WaitForChild("ToggleStatus")
local GameMusicSettingToggleStatus = GameMusicSettingToggleClick:WaitForChild("ToggleStatus")
local PartyMusicSettingToggleStatus = PartyMusicSettingToggleClick:WaitForChild("ToggleStatus")
local ShadowsSettingToggleStatus = ShadowsSettingToggleClick:WaitForChild("ToggleStatus")
local TransitionsSettingToggleStatus = TransitionsSettingToggleClick:WaitForChild("ToggleStatus")

local TweenInfo1 = TweenInfo.new(
	0.2,
	Enum.EasingStyle.Linear,
	Enum.EasingDirection.InOut,
	0,
	false,
	0
)

-- The table in which settings you can not toggle on or off are stored.
local DebouncedSettings = {}

-- The function that runs when the toggle button is pressed.
local function ToggleToggleFrameAppearance(ToggleFrame, TrueOrFalse, IsServerRequest)
	if ToggleFrame == nil then return end
	if TrueOrFalse == nil then return end

	-- This is the setting name, it will always be a string.
	local SettingName = ToggleFrame.Parent.Parent.Parent.Name
	-- The rest here is just for animation purposes.
	local ToggleDot = ToggleFrame:WaitForChild("ToggleDot")
	local Tween = TweenService:Create(ToggleFrame, TweenInfo1, {BackgroundColor3 = Color3.fromRGB(255, 0, 0)})
	local Tween2 = TweenService:Create(ToggleFrame, TweenInfo1, {BackgroundColor3 = Color3.fromRGB(0, 255, 0)})
	local Tween3 = TweenService:Create(ToggleDot, TweenInfo1, {Position = UDim2.new(0.2, 0,0.5, 0)})
	local Tween4 = TweenService:Create(ToggleDot, TweenInfo1, {Position = UDim2.new(0.8, 0,0.5, 0)})

	-- This is just if I need to instantly toggle a setting on or off from the server, this doesn't need to be in a debounce.
	if IsServerRequest ~= nil and IsServerRequest == true then
		if TrueOrFalse == true then
			Tween2:Play()
			Tween4:Play()
		else
			Tween:Play()
			Tween3:Play()
		end
	else
		-- So here is where it should be checked if the setting is in the table, and if its not put it inside the table and it shouldn't be allowed to be toggled off or on momentarily.
		-- The TrueOrFalse variable just tells the code whether or not to enable a setting. True means to enable it while false means to disable it.
		if Debounce then
			return
		end
		Debounce = true
		if TrueOrFalse == true then
			Tween2:Play()
			Tween4:Play()
			Tween4.Completed:Wait()
			wait(0.1)
			-- The setting should be allowed to be toggled now so remove it from the table.
		else
			Tween:Play()
			Tween3:Play()
			Tween3.Completed:Wait()
			wait(0.1)
			-- The setting should be allowed to be toggled now so remove it from the table.
		end
		task.wait(1)
		Debounce = false
	end
end

-- This is something else not needed to be touched.
local function UpdateCurrentSongText()
	CurrentSongText.Text = "Current Song: " .. CurrentSong.Value
end

UpdateCurrentSongText()

-- This here triggers the toggling of the setting if a button is clicked. Toggle status just has the default value of whether or not a setting is enabled. It is a boolean value.
AFKModeSettingToggleClick.MouseButton1Down:Connect(function()
	AFKModeSettingToggleStatus.Value = not AFKModeSettingToggleStatus.Value
end)

VIPTrailSettingToggleClick.MouseButton1Down:Connect(function()
	VIPTrailSettingToggleStatus.Value = not VIPTrailSettingToggleStatus.Value
end)

GameMusicSettingToggleClick.MouseButton1Down:Connect(function()
	GameMusicSettingToggleStatus.Value = not GameMusicSettingToggleStatus.Value
end)

PartyMusicSettingToggleClick.MouseButton1Down:Connect(function()
	PartyMusicSettingToggleStatus.Value = not PartyMusicSettingToggleStatus.Value
end)

ShadowsSettingToggleClick.MouseButton1Down:Connect(function()
	ShadowsSettingToggleStatus.Value = not ShadowsSettingToggleStatus.Value
end)

TransitionsSettingToggleClick.MouseButton1Down:Connect(function()
	TransitionsSettingToggleStatus.Value = not TransitionsSettingToggleStatus.Value
end)

AFKModeSettingToggleStatus.Changed:Connect(function()
	ToggleToggleFrameAppearance(AFKModeSettingToggleFrame, AFKModeSettingToggleStatus.Value)
end)

VIPTrailSettingToggleStatus.Changed:Connect(function()
	ToggleToggleFrameAppearance(VIPTrailSettingToggleFrame, VIPTrailSettingToggleStatus.Value)
end)

GameMusicSettingToggleStatus.Changed:Connect(function()
	ToggleToggleFrameAppearance(GameMusicSettingToggleFrame, GameMusicSettingToggleStatus.Value)
end)

PartyMusicSettingToggleStatus.Changed:Connect(function()
	ToggleToggleFrameAppearance(PartyMusicSettingToggleFrame, PartyMusicSettingToggleStatus.Value)
end)

ShadowsSettingToggleStatus.Changed:Connect(function()
	ToggleToggleFrameAppearance(ShadowsSettingToggleFrame, ShadowsSettingToggleStatus.Value)
end)

TransitionsSettingToggleStatus.Changed:Connect(function()
	ToggleToggleFrameAppearance(TransitionsSettingToggleFrame, TransitionsSettingToggleStatus.Value)
end)

-- This is something else not needed to be touched.
CurrentSong.Changed:Connect(function()
	UpdateCurrentSongText()
end)

Change “task.wait(1)” if you need to increase/decrease the debounce length.

There is no debounce currently, because I don’t know how to implement it properly.

I added one, check the section where you commented that you needed one.

After testing that code it appears that I can only toggle one setting once and then I can not toggle it or any others again.

Oh my bad, looks like it does work. But I can only toggle one setting and if I try to toggle another one it doesn’t let me until the original debounce time is over. I need a debounce for each setting if possible.

I have figured out the way to implement this properly myself. Thank you for the help!