Scripting HelpersARCHIVE
A little piece of Roblox history. Preserved for everyone, one question at a time.Read about the archive →
✓ ANSWER ACCEPTED

Trying to make a wait but it doesn't well, wait?

This wait does not work idk why but it just wont stay is there anyway to make it wait in between hits?

function onTouched(hit)

	local human = hit.Parent:findFirstChild("Humanoid")
	damage = script.Parent.Parent.EnemySettings.Damage.Value

	if (human ~= nil) then
		wait(2)
		human.Health = human.Health - damage
	end
end

script.Parent.Touched:connect(onTouched)

2 answers

✓ Accepted answer

Events

Every time an event fires, the code inside the function it's associated with (also known as it's callback) runs as it's own individual task. It would essentially be the same as spawning a function, or taking advantage of the coroutine library. This just means when you call a yielded function, it will only effect that task while the others take their turn to execute. This is because coroutines actually take turns running instead of running simultaneously, but that's for a different discussion.

Debounce

Debounce is the solution you're really looking for. Debounce acts as a gate between what can and can't happen, and is typically controlled using boolean values (true and false) with an if statement to check their conditions. It's important to toggle this value, however. If you leave your debounce in a single state, the body of your code will only run once (assuming you've switched it at least once).

The entire point of using a debounce is to give it a default value (in this case we're going to assign it true by default), then evaluate it while also inverting it (so the condition will differ next time around).

Implementation

The description I gave above may seem convoluted, but it's really simple. It's just a yes/no condition in a program to execute a body of instructions. Here's an example:

local debounce = true -- Debounce condition

local function sample()
	if debounce == true then -- If debounce is true, then...
		debounce = false -- Notice we change it immediately, so the body of code won't run next time the condition is evaluated.
		print("This code has ran!")

	-- If the debounce isn't true, however
	else

		-- Immediately invert it.
		debounce = true

		-- Run this segment
		print("Waiting to run code")
	end
end
		
-- Execute the function 3 times.
sample()
sample()
sample()

If you run the code above, you'll see you get these results:

This code has ran!

Waiting to run code

This code has ran!

However, there is a shorter way we could word this. Most of the time, people only care about the part of the debounce that allows the code to run, and don't care about an alternative set of instructions. To implement a shorter version, we could simply check if debounce is false, and if it is then use the return statement to discontinue the execution of the body it's a descendant of. We'll still have to toggle the value, however. Example:

local debounce = true

local function sample()
	if not debounce then
		return
	end

	-- Immediately toggle the debounce
	debounce = false

	-- Body
	print("The debounce must be true if you see this!")
	wait(1)
	debounce = true -- Allow the function to execute the main part of it's body again (after waiting one second)
end

-- Call it 3 times
-- Notice it will only print once, then again after 1.5 seconds (since that's when we set our debounce back to true)
sample()
sample()
wait(1.5)
sample()

Needless to say, there's a million ways you can implement debounce, so I'm not going to cover any more examples. Furthermore, here would be your revised code using debounce to wait before firing the event more than once at a time:

local debounce = true

script.Parent.Touched:connect(function(hit)
	if debounce == false then
		return
	end

	debounce = false

	local human = hit.Parent:FindFirstChild("Humanoid")
	local damage = script.Parent.Parent.EnemySettings.Damage.Value

	if human then
		wait(2)
		human.Health = human.Health - damage
	end

	debounce = true
end)

Hope this helped, let me know if you have any questions.

3 comments

0

Thanks so much and as a bonus i now know how to use debounce! my only question is that actually something that roblox made or did developers just decide to use it?

0

Why are you using elseif when you mean else?

0

Not sure, thanks for pointing that out. Corrected it.

Okay so, the wait inside the function is useless because the Touched event can still be fired multiple times, in order to have it wait you must use debounces.

local debounce = true -- Create the debounce

function onTouched(hit)

    local human = hit.Parent:findFirstChild("Humanoid")
    damage = script.Parent.Parent.EnemySettings.Damage.Value

    if (human ~= nil)  and debounce == true then -- Only deal damage if debounce is equal to true
	debounce = false -- Damage is dealt and Debounce is now set to false
        human.Health = human.Health - damage
    end
end

script.Parent.Touched:connect(onTouched)

wait(2)
debounce = true -- Wait 2 seconds and then set debounce to true again so damage can be dealt

1 comment

0

Make sure to stick the last two lines of your code into the event, or else it will not work.

This discussion is preserved as it was. New answers, comments, and votes are closed.