Weird debounce bug?

Ok, I’ve never been any more frustrated in my life then I am now. Roblox isn’t making any sense for me right now and I need help on whatever is going on.

Basically, I have this simple hit script

Mouse.Button1Down:Connect(function()
	if Debounce == false then
		
		Debounce = true
		CanHit = true
		
		game.ReplicatedStorage.RemoteEvents.PlayWoosh:FireServer()
		
		StrikeAnimation:Play()
		
		GlobalStrikeAnimation:Play()
		
		delay(.65,function()
			Debounce = false
			CanHit = false
		end)
	end
end)

WeaponModel.Stick.Touched:Connect(function(Target)
	spawn(function()
		if CanHit == true then

			local Hit, Kill = game.ReplicatedStorage.RemoteEvents.CheckMeleeHit:InvokeServer(Target,Weapon)

			if Hit ~= nil then
				
				print("HIT!")

				CanHit = false

				Player.PlayerGui.Game.Sounds.Hit:Play()

				Mouse.Icon = "http://www.roblox.com/asset/?id=6951512894"

				wait(.25)

				Mouse.Icon = "http://www.roblox.com/asset/?id=409468479"
			end

			if Kill == true then
				game.ReplicatedStorage.RemoteEvents.Kill:Fire(Hit)
			end
		end
	end)
end)

Simple right? It’s a knife script with a debounce so people can’t spam it, but for SOME REASON, the debounce portion isn’t working. “Hit!” is getting printed twice on some knife strikes, even though I have the debounce incorporated. What should be happening is canhit is true initially, then if Hit ~= nil meaning that the player has hit someone, canhit is false. Making it impossible to be able to hit again until the debounce is finished.

Does anyone know what is going on here???

(You can see “HIT!” is printed twice)

Try changing your script so that you set CanHit = false immediately after checking if it’s true.

It could be that it hit’s more than one thing during the brief period of time it is allowed to hit, for example the arm and torso.

This won’t make it work 100% of the time, since the weapon will most likely be hitting things other than a player. And once it hits something player or not, it locks it completely.

But wouldn’t it not be able to hit torso after it hit’s arm? Because I set CanHit to false

Then add a line that changes CanHit = true if the player isn’t hitting a character.

How about if Hit ~= nil and CanHit then (leave your initial CanHit check above that as it is, just check again after the server response)
Cuz right now what’s probably happening is that you check CanHit first, ask server for confirmation which halts the progress before changing CanHit to false, meanwhile hits other thing and since CanHit is still true it asks the server again but it’s already past the CanHit check

If you meant like this

WeaponModel.Stick.Touched:Connect(function(Target)
	spawn(function()
		if CanHit == true then

			local Hit, Kill = game.ReplicatedStorage.RemoteEvents.CheckMeleeHit:InvokeServer(Target,Weapon)
			
			CanHit = false
			
			if Hit ~= nil then

				Player.PlayerGui.Game.Sounds.Hit:Play()

				Mouse.Icon = "http://www.roblox.com/asset/?id=6951512894"

				wait(.25)

				Mouse.Icon = "http://www.roblox.com/asset/?id=409468479"
			else
				CanHit = true
			end

			if Kill == true then
				game.ReplicatedStorage.RemoteEvents.Kill:Fire(Hit)
			end
		end
	end)
end)

Then it still didn’t work. Maybe the Invocation of CheckMeleeHit somehow breaks the script?

What I meant was to set CanHit to false before invoking the server.

I think this might have worked! Hit is only printing once now but for some reason it still does double damage sometimes. So maybe it didn’t work?

Actually, it didn’t work. The invocation is still going twice but the feedback just isn’t

But still set it to true if it didn’t hit right?

This inflicts the damage I assume - as I said above, it goes through on client side multiple times through the CanHit check and calls the remote function multiple times - so you should probably have debounce on server

Having debounce server-side for each player is also much better against hackers - the attacks can be spammed on client-side, however, the damage will be correctly inflicted. Imagine shooting a thousand shots but server lets only one of them do damage (client-side debounce is great for animations and visuals that only the player sees tho)

This is because the kill event is in a separate conditional. You would need to test for the same conditions as before (if the player hit a character and if the debounce is true).

I could probably do that but I would have to spawn a function every single time it checks because of the wait in the debounce. And it would have to do it for every player. Wouldn’t that be inefficient?

You could just remember the last time client requested to hit (with something like tick() ) and next time they send a request you just compare new tick() with the previous one and save it to the same variable/table and compare them to see if the debounce time has passed

Talking about spawning functions… There is no need to do that in the Touched event connect since each event does that already with connections

Yeah That was just my random fixing due to frustration. But I’m talking about the server script. Wouldn’t I have to account for each player on their denounce? It sounds really complicated.

Oh ok. That could work. Thanks!

1 Like
local Script = script
local Tool = Script.Parent
local Handle = Tool.Handle

local function OnTouched()
	--Do code here.
end

local function OnActivated()
	local Connection	
	Connection = Handle.Touched:Connect(OnTouched)
	task.wait(0.3) --Activation duration.
	Connection:Disconnect()
end

Tool.Activated:Connect(OnActivated)

You could just connect the weapon’s Touched signal whenever it is activated and subsequently disconnect it after some time has elapsed.