Implementing Debounce while using coroutine.wrap and FireClient()

I came up with a script that fires an event for the client, (fireclient) from the server, that is fired once a player touches a part.

it does work, but it actually fires 10-15 times for as long as the player is on the part (in contact)

Here is the script I used in the part

local players = game:GetService("Players")
local stepped = false

if stepped == true then stepped = false wait(1) else wait(1.1)
script.Parent.Touched:Connect(function(hit)
    local touchedPlayer = players:GetPlayerFromCharacter(hit.Parent)
    if touchedPlayer then
        for _, loopedPlayer in pairs(players:GetPlayers()) do
           
                coroutine.wrap(function() 
                   wait(1)
             local event =  game.ReplicatedStorage.CompleteEvent
                event:FireClient(touchedPlayer)
               for _, loopedPlayer in pairs(players:GetPlayers()) do
        
    if loopedPlayer:FindFirstChild("PlayerGui") then

  local Complete = loopedPlayer.PlayerGui.ScreenGui.complete
                    Complete.Visible = true
                    Complete.Text = "Wow !" .. touchedPlayer.Name .. " has climbed the Un-Climbable Stairs !"
                    wait(3.3)
                      Complete.Visible = false              
 
         stepped=true    
           
         end       
        end                
 end)()
      end
     end
  end)
end

Basically if there is a folder called folder2, containing the bool ‘completed’ , if that is found in the folder , and it is true, then nothing happens at all, but if the value is false then a gui is shown , and the value is set to true, so that we know he has completed .

My script in StarterPlayerScripts//local script

local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
 
local player = Players.LocalPlayer
local event = ReplicatedStorage:WaitForChild("CompleteEvent")


 
event.OnClientEvent:Connect(function(player)
	    wait(0.8)
	 if  player.folder2.completed.Value == true then
		 return print("already true")
		
	end
	
	wait(0.7)
	
	
              
	
 player.leaderstats.Cash.Value = player.leaderstats.Cash.Value + 100
   print("added")
 player.folder2.completed.Value = true
   print("value set to true, you have received the cash")    
        
              end)

Thanks for helping me out

Have a variable called “active” and put it inside your Touched function.

if active ~= true then
 -- code
end

Once you want the user to be able to run the code again, set active to false.

First off all, why are you changing the leaderstats on the client? The change will not replicate to the server and changes will not be saved if you’re using a datastore.

Second of all, the descendants of PlayerGui will not be replicated to the server, because they are cloned on the client, unless you’re cloning it on the server

Finally, you could try this:

local deb = false

script.Parent.Touched:Connect(function(hit)
    local touchedPlayer = players:GetPlayerFromCharacter(hit.Parent)
    if touchedPlayer and not deb then
        deb = true
        -- after everything was completed and after a wait()
        deb = false
    end
1 Like

You mean i’ll have to use invoke client or something similar…?
So I can use a serverscript to detect whether it’s been touched, and then a local one and then another server script ?
Because I want to change points on the server, I forgot about that , but since there is no way to detect a change in a local script , (TouchedEvent) and no way to use a server script to fire server

Alright so, you’ll apply a debounce like you would for anything really.
A boolean variable, which is checked to be true, set a cooldown and then set to false.

Now the value you change for “CompleteEvent” should be executed on the Server, as per replication.
You can check the value of Completed on the server, so no worries about that.

You’ll need a RemoteEvent for the UI changing however, all of UI scripting should be done on the Client.

Now putting that into action:

local debounce = true
local players = game:GetService("Players")

script.Parent.Touched:Connect(function(hit)
    local touchedPlayer = players:GetPlayerFromCharacter(hit.Parent)
    if touchedPlayer and debounce then
        debounce = false
        --// Give the touchedPlayer Cash
        --// FireAllClients a RemoteEvent, where you'll Connect OnClientEvent in the UI and update it
        wait(2) --// Cooldown
        debounce = true
    end
end)
2 Likes

Here’s a methodology you can use:

  1. Server will detect the part getting touched and check if it’s not currently in a cooldown
  2. Server will give cash
  3. Call FireAllClients on a RemoteEvent, where in the local script, will update the UI
  4. Apply cooldown
1 Like