Debounce Doesn't seem to be working

Hello,
This code is gives a random amount of credits when the checkpoint is reached but it runs multiple times despite having a debounce if I touch the checkpoint it gives me about 1000 credits like there is a delay. Thanks for any help.

for _, part in cs:GetTagged("checkpoint") do
	
	local soundPlayed = false
	local creditsGiven = false
	
	part.Touched:Connect(function(hit)
		if hit.Parent:FindFirstChild("Humanoid") then
			
			-- Creates a random coin amount
			local randomCreditAmount = math.random(100, 250)
			
		if soundPlayed == false then
			soundPlayed = true
			local soundClone = script.CheckpointSound:Clone()
		soundClone.Parent = part
		soundClone:Play()
	
		-- Updates the players coin value
		if creditsGiven == false then
			creditsGiven = true
			game.Players:GetPlayerFromCharacter(hit.Parent).leaderstats["Neon Credits"].Value += randomCreditAmount
			print("Credits Given")
		end
3 Likes

Are there more parts to the code? Is there a piece of code where you reset the debounces?

1 Like

It doesn’t reset but here is the entire code

local cs = game:GetService("CollectionService")
local remoteEvent = game.ReplicatedStorage.FakeRespawnPlayer

local electricSound = script.ShockLoop

cs:GetInstanceAddedSignal("checkpoint"):Connect(function()
for _, part in cs:GetTagged("checkpoint") do
	
	local soundPlayed = false
	local creditsGiven = false
	
	part.Touched:Connect(function(hit)
		if hit.Parent:FindFirstChild("Humanoid") then
			
			-- Creates a random coin amount
			local randomCreditAmount = math.random(100, 250)
			
		if soundPlayed == false then
			soundPlayed = true
			local soundClone = script.CheckpointSound:Clone()
		soundClone.Parent = part
		soundClone:Play()
	
		-- Updates the players coin value
		if creditsGiven == false then
			creditsGiven = true
			game.Players:GetPlayerFromCharacter(hit.Parent).leaderstats["Neon Credits"].Value += randomCreditAmount
			print("Credits Given")
		end
			
		end
		
			part.Color = Color3.new(0, 1, 0.333333)
				-- Saves a vector3 value
			game.Players:GetPlayerFromCharacter(hit.Parent):SetAttribute("CurrentCheckpoint", part.Position)
			print("Checkpoint Saved")
		end
end)
end
end)

cs:GetInstanceAddedSignal("resetBrick"):Connect(function()
	for _, part in cs:GetTagged("resetBrick") do
	part.Touched:Connect(function(hit)
		if hit.Parent:FindFirstChild("Humanoid") then
			print("Damage hit")
			hit.Parent.HumanoidRootPart.Position = game.Players:GetPlayerFromCharacter(hit.Parent):GetAttribute("CurrentCheckpoint")
		end
	end)
	
		local soundClone = electricSound:Clone()
		soundClone.Parent = part
		soundClone:Play()
		print("Playing Sound")
	end
end)

Sorry its a little messy but this script controls two things so the second cs function isn’t related to the problem

Try putting these in the touched event.

This will only worsen the problem

1 Like

How will this worsen the problem?

Though your debounces aren’t actually debounces, there’s nothing in your code that is allowing your checkpoints to deliver their rewards more than once to the first entity that touches them. Are you seeing a repeated output of “Credits Given”? If so, try replacing your print call with the following:

print(debug.traceback("Credits Given"))

This will help you understand more about where the print call is being made. Maybe you have multiple instances of the same programming running

Try to make soundPlayed and creditsGiven instances inside every checkpoint. The variables return to their value for each time it’s looped

local soundPlayed = Instance.new("BoolValue")
soundPlayed.Name = "soundPlayed"
soundPlayed.Value = false
soundPlayed.Parent = part

local creditsGiven = Instance.new("BoolValue")
creditsGiven.Name = "creditsGiven"
creditsGiven.Value = false
creditsGiven.Parent = part
Full Code
cs:GetInstanceAddedSignal("checkpoint"):Connect(function()
	for _, part in cs:GetTagged("checkpoint") do
		local soundPlayed = part:FindFirstChild("soundPlayed")
		local creditsGiven = part:FindFirstChild("creditsGiven")
		
		if not soundPlayed then
			soundPlayed = Instance.new("BoolValue")
			soundPlayed.Name = "soundPlayed"
			soundPlayed.Value = false
			soundPlayed.Parent = part
		end
		if not creditsGiven then
			creditsGiven = Instance.new("BoolValue")
			creditsGiven.Name = "creditsGiven"
			creditsGiven.Value = false
			creditsGiven.Parent = part
		end

		part.Touched:Connect(function(hit)
			if hit.Parent:FindFirstChild("Humanoid") then

				-- Creates a random coin amount
				local randomCreditAmount = math.random(100, 250)

				if soundPlayed.Value == false then
					soundPlayed.Value = true
					local soundClone = script.CheckpointSound:Clone()
					soundClone.Parent = part
					soundClone:Play()

					-- Updates the players coin value
					if creditsGiven.Value == false then
						creditsGiven.Value = true
						game.Players:GetPlayerFromCharacter(hit.Parent).leaderstats["Neon Credits"].Value += randomCreditAmount
						print("Credits Given")
					end

				end

				part.Color = Color3.new(0, 1, 0.333333)
				-- Saves a vector3 value
				game.Players:GetPlayerFromCharacter(hit.Parent):SetAttribute("CurrentCheckpoint", part.Position)
				print("Checkpoint Saved")
			end
		end)
	end
end)

By placing these variables within the event listener, their effect on the execution of the event listener becomes ephemeral; they’ll be reset the next time the event is invoked, essentially making them redundant. This would actually allow more than one player to claim the checkpoint multiple times

Than what is the solution to the problem?

This is functionally equivalent to what OP has already. The variables created each iteration are not lost as they’re cached as upvalues in the event listener’s closure—each variable is unique to each event listener. You can see this in action with the following code:

local memories = {}

for number = 1, 3 do
	local function memory()
		print(number)
	end
	
	table.insert(memories, memory)
end

for _, memory in memories do
    memory()
end

Output

1
2
3

Never mind, I see your problem. Each time a new checkpoint is added, you’re iterating through all existing checkpoints and duplicating the existing event listeners. Your “debounces” were working, you just had multiple responses to the same collision with a single checkpoint.

cs:GetInstanceAddedSignal("checkpoint"):Connect(function()
	for _, part in cs:GetTagged("checkpoint") do

Change your code to the following:

local function initializeCheckpoint(checkpoint)
    -- The body of your "for _, part in cs:GetTagged("checkpoint") do" loop.
end
for _, checkpoint in cs:GetTagged("checkpooint") do
    initializeCheckpoint(checkpoint)
end

cs:GetInstanceAddedSignal("checkpoint"):Connect(initializeCheckpoint)

This code separates the initialization of all existing checkpoints from the initialization of individual future checkpoints. Here is a fully revised version:

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local CollectionService = game:GetService("CollectionService")
local Players           = game:GetService("Players")


local REWARD_MIN = 100
local REWARD_MAX = 250


local ShockLoopSound = script.ShockLoop



local function onLivingPlayerTouched(part: BasePart, callback: (player) -> ()): RBXScriptConnection
	return part.Touched:Connect(function(otherPart: BasePart)
		local character = otherPart.Parent

		local humanoid = character:FindFirstChildOfClass("Humanoid")
		if not humanoid or humanoid.Health <= 0 then
			return
		end

		local player = Players:GetPlayerFromCharacter(character)
		if not player then
			return
		end

		callback(player)
	end)
end

local function initializeCheckpoint(checkpoint: BasePart)
	local connection: RBXScriptConnection
	
	connection = onLivingPlayerTouched(checkpoint, function(player: Player)
		connection:Disconnect()
		
		local leaderstats = player.leaderstats
		local neonCredits = leaderstats["Neon Credits"]
		
		neonCredits.Value += math.random(REWARD_MIN, REWARD_MAX)
		
		checkpoint.Color = Color3.fromRGB(0, 255, 85)
	end)
end

local function initializeResetBrick(resetBrick: BasePart)
	local shockLoopSound  = ShockLoopSound:Clone()
	shockLoopSound.Parent = resetBrick
	
	onLivingPlayerTouched(resetBrick, function(player: Player)
		shockLoopSound:Play()
		
		player.Character:PivotTo(CFrame.new(player:GetAttribute("CurrentCheckpoint")))
	end)
end

local function initializeAll(tag: string, initializer: (BasePart) -> ())
	for _, tagged in CollectionService:GetTagged(tag) do
		initializer(tagged)
	end
	
	CollectionService:GetInstanceAddedSignal(tag):Connect(initializer)
end



initializeAll("Checkpoint", initializeCheckpoint)
initializeAll("ResetBrick", initializeResetBrick)
1 Like

maybe try this

for _, part in cs:GetTagged("checkpoint") do
	local rewarded = false
	
	part.Touched:Connect(function(hit)
		if hit.Parent:FindFirstChild("Humanoid") and not rewarded then
            rewarded = true

		    local soundClone = script.CheckpointSound:Clone()
		    soundClone.Parent = part
		    soundClone:Play()
	
		    -- Creates a random coin amount
			local randomCreditAmount = math.random(100, 250)

            local player = game.Players:GetPlayerFromCharacter(hit.Parent)
		    player.leaderstats["Neon Credits"].Value += randomCreditAmount
		    print("Credits Given")
        end
    end)
end

if it doesn’t work, then you probably have multiple parts in the checkpoint being tagged or something

1 Like

Well its a round based system so everytime the round is over all the tagged instances are destroyed and the map doesn’t exist until a player is loaded into the game so there are no initial checkpoints only generated checkpoints

That doesn’t matter. The fact that the checkpoints are loaded in triggers the event created with GetInstanceAddedSigal. This then leads to the problem I stated before, which is how you loop over all checkpoints that were loaded prior to those still loading and duplicate their event listeners. Try the solution I gave to you, or use my fully revised code. Do note that it does not exactly align with your current code, so some changes will need to be made

1 Like

I used the the revised code but it doesn’t seem to be working and no errors are being outputted

The only relevant difference between the revised code and your current code is that I used the proper naming convention for your tags (PascalCase). Did you make sure to update your tags to reflect this, or did you change my script to work with your current tags (camelCase)?

1 Like

mb it works im just blind :laughing: thx I thought I was going to have to go the lazy way and just make the prices high lol

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