[HELP] Delete part when .Touched without latency or concurring/running multiple times

I made this script, that if the ball detects that it has touched the ground, it places this “surface” and after it deletes itself. The problem is that if I click from afar, the sphere will go towards that spot while touching the ground multiple times, making multiple duplicated surfaces.

I’ve tried a debounce and it either didn’t work or I’m just bad at making debounces. What I don’t like about having a debounce is that it adds a cooldown (Something which I don’t want).

(I’m new to scripting, so getting tips/feedback from you guys would be amazing!)

Here’s the script:

		clone.Touched:Connect(function(hit)
			local playable = hit:GetAttribute("playable")
			if playable == true then
				debris:AddItem(clone,0.1)


				local surfaceClone = surfaceRX:Clone()
				local rotation = Vector3.new(0, 0, 90)


				surfaceClone:SetAttribute("surElement", "water")
				surfaceClone.Parent = workspace
				surfaceClone.Position = mouseHit.p
				surfaceClone.hitBox.Position = mouseHit.p + Vector3.new(0,1.1,0)
				surfaceClone.Rotation = rotation

					--if surfaceClone.Parent == workspace then
					--	local waterEffectClone = waterEffect:Clone()
					--	waterEffectClone.Parent = workspace
					--	waterEffectClone.Anchored = true
					--	wait(0.05)
					--	waterEffectClone.Position = surfaceClone.Position
					--	makePartBiggerTween:Play()
					--	wait(0.2)
					--	makePartSmallerTween:Play()
					--end

					-- Effects/Anims that also don't work because a lot of Touch Detections ^


				if hit.Name == "groundSurface" and hit:GetAttribute("surElement") == "fire"  then
					debris:AddItem(hit,0)
				elseif hit.Parent:FindFirstChild("Humanoid") then
					local enemyHealth = hit.Parent.Humanoid
					enemyHealth:TakeDamage(waterDmg)
				end
			end
		end)

13f95155d874f0db68821643a94c4464

Whenever we detect a hit part with the “playable” attribute set to true is when we create the surface part. Therefore, once we receive confirmation, we don’t want this to fire again. This is a debounce we can implement to prevent multiple triggers:

local hasTriggered = false

clone.Touched:Connect(function(hit)
    if hasTriggered then return end --If we've already had a valid detection, we stop the function

    local playable = hit:GetAttribute("playable")

    if playable == true then --All criteria have been met
        hasTriggered = true --So we set the debounce to true

        debris:AddItem(clone,0.1)

        local surfaceClone = surfaceRX:Clone()
		local rotation = Vector3.new(0, 0, 90)

		surfaceClone:SetAttribute("surElement", "water")
		surfaceClone.Parent = workspace
		surfaceClone.Position = mouseHit.p
		surfaceClone.hitBox.Position = mouseHit.p + Vector3.new(0,1.1,0)
		surfaceClone.Rotation = rotation

		if hit.Name == "groundSurface" and hit:GetAttribute("surElement") == "fire"  then
			debris:AddItem(hit,0)
		elseif hit.Parent:FindFirstChild("Humanoid") then
			local enemyHealth = hit.Parent.Humanoid
			enemyHealth:TakeDamage(waterDmg)
		end
	end
end)

This also removes the need to depend on the Debris service to handle the part.

Hope this helps!

1 Like

You can try disconnecting the event:

local connection 
connection = clone.Touched:Connect(function(hit)
	connection:Disconnect() --not letting it fire again
	--code goes here
end)
1 Like

Even though this works, the function is meant to constantly be able to fire once again, if I put this it stops the function completely, allowing me to fire the projectile only once.

This helped! Thank you very much, but question… how can I tell where and when to put a debounce? I really don’t understand the concept a lot… or I can’t get it inside my head at least :joy:

Thanks though, at least you taught me how to disconnect :joy:, I wasn’t able to use disconnect ever, so I might try it on future scripts.

1 Like

If you’re creating a new clone each time the projectile fires and connect it to a new .Touched it will work as expected.

1 Like

Oohhhh, that also makes sense…

Whenever all the conditions have been met for an action to take place, that’s the exact instant we set the value of a debounce!

Notice where that moment is in your script: right after we find a hit part with the playable value set to true, we know we can now place the surface part; so if we set the debounce to true, the function will finish completing the action we wanted to happen and we will have prevented the function from executing again.

1 Like

That blows my mind… I’m still doubtful I’m capable of using it… I’m gonna start practicing with debounces, cause- damn.

Watching and hearing how it works might help you out a bit, here’s a tutorial I found on YouTube:

ROBLOX Lua Scripting Tutorial 12 - Debounce - YouTube

Nonetheless, practice makes perfect! Play around with simple examples and see what happens.

1 Like

Thank you very much!! You helped a lot, have a good one!

1 Like

I practiced a little bit with another function I wanted to do, and I think I got it! Thank you very much! but there’s still this weird thing that the touch + debounce is doing, but I’ll figure it out. Have a good one!

I ran into a problem that I do not know how to fix. (Still with debounce), I thought I got the concept of it, but… I remembered that the script will start over, and whatever the value is set to, it won’t matter if ran again. Therefore, the function will repeat as many times as you start the script.

I’m trying to set a surface, and if it’s already placed and the character is hit once again, it shouldn’t place another surface on top.

Code:

Vid:
0d2df71244b43caffa6c1d350ae29c3e