Help with debounce on Touched event

I want to set a boolean to true when a player touches a part, and set it to false if the player walk off, and set it back to true if the player touches the part again, but the boolean keeps switching between true and false when the player walks all over the part, i would love some help, this is my script so far.

local debounce = false
local foobar = false
script.Parent.Touched:Connect(function(hit)
	if hit.Parent:FindFirstChild("Humanoid") then
		if debounce == false then
			print("touched")
			debounce = true
            foobar = true
		end
	end
end)

script.Parent.TouchEnded:Connect(function(hit)
	if hit.Parent:FindFirstChild("Humanoid") then
        debounce = false
        foobar = false
    end
end)

Is this really the only code you have here? I just tested this on my end and it prints “touched” once and doesn’t do anything else, as expected since debounce is never set back to false and remains true forever.

Would you happen to have any other code? There’s just no possible way that with this code alone, it’s switching back and forth between true and false.

Well you might want to put a wait() between the print() and Debounce = true, as this wait acts like the cool down timer

The value keep changing because roblox thinks your character touched the part multiple times even if you are just standing on it.

This does not help… Adding a wait() before the debounce is turned on results in the possibility of multiple print statements instead of exactly one before debounce is turned on. The whole purpose of a debounce is to prevent things from repeatedly happening. A wait() makes no sense before debounce is set to true.

I tested this code on my end. I put it in a script parented to a part in workspace and it only printed once when a humanoid touched it. The debounce isn’t even switching back to false in this case, it’s just being set to true and then never changing. I’m not quite sure how this code could be causing the debounce to switch back and forth

Excuse moi, absolutely. The Debounce = true should be the first line right after the if statement, the wait() needs to at about the end right before the Debounce = false statement is added

Oh, my bad, I have corrected the code now

1 Like

Oh, well this is easy then.

What’s happening is when your character walks all over the part, the legs of the character are moving up and down, causing multiple Touched events and then multiple TouchEnded events to occur. That’s why this occurs.

I also honestly don’t recommend using TouchEnded at all as it’s notoriously unreliable, but if you have to, I would have it to where the code makes sure that it only triggers when the player’s HumanoidRootPart is the one touching it. This is because the HumanoidRootPart is a special part of the player that doesn’t shake around or anything during animations.

This is of course a bit of a problem as I assume the part in question is being walked on which means the HumanoidRootPart can’t even reach it. You could have an invisible part on top of the part in question that is just high enough for the HumanoidRootPart to reach and have the Touched and TouchEnded events be connected to that instead.

Alternatively, you could abandon TouchEnded altogether and wait for the player to be a certain distance away from the part before setting the debounce back to false. Use (part.Position - player.HumanoidRootPart.Position).Magnitude to get the distance between the player and the part.

My favorite alternative would probably be GetTouchingParts(). You can use this on the part to get all the parts touching it and just check if its parent is the player. Then, to determine when the player has left the part, if GetTouchingParts() returns no parts parented to the player, you just set the debounce to false again.

Here, I’m using it in combination with Touched:

local debounce = false
part.Touched:Connect(function(part)
    if part.Parent:FindFirstChild("Humanoid") and debounce == false then
        debounce = true

        -- now using GetTouchingParts()
        while debounce == true do
           local touchingParts = part:GetTouchingParts()
           local foundPlayerPart = nil
           for _, part in pairs(touchingParts) do
              if part.Parent:FindFirstChild("Humanoid") then
                  foundPlayerPart = true
                  break
              end
           end
           if foundPlayerPart == true then
               debounce = false
           else
               wait()
           end
        end
    end
end)