I made a Stopwatch Script for my Speedrun game but when a Timer is already running and a any player touches the timer start block it resets the timer for everyone
Here is the code:
[CODE lang="lua" title="Stopwatch"]local Time = script.Parent
local running = true
local start = game.Workspace.StartSpawn.Coll
local finish = game.Workspace.Top.Door
function PlayTimer()
local Start = tick()
while running do
wait()
local Difference = tick() - Start
local Minutes = math.floor(Difference / 60)
local Seconds = Difference - Minutes * 60
local Millisecond = math.floor((Seconds - math.floor(Seconds))*10)
Seconds = math.floor(Seconds)
local Milliseconds, replaced = string.gsub(Millisecond, "", "")
if string.len(Seconds) < 2 then Seconds = "0" .. Seconds end
if string.len(Minutes) < 2 then Minutes = "0" .. Minutes end
local Format = Minutes .. ":" .. Seconds .. ":" .. Milliseconds
Time.Text = Format
end
end
start.Touched:connect(function(hit)
if hit and hit.Parent and hit.Parent:FindFirstChild("Humanoid") then
running = false
wait(0.01)
running = true
PlayTimer()
end
end)
finish.Touched:connect(function(hit)
if hit and hit.Parent and hit.Parent:FindFirstChild("Humanoid") then
running = false
end
end)[/CODE]
I'd also suggest a couple optimizations, like using
modulus and
string formatting.
Connect
should also be capitalized now, without it's technically considered deprecated. Using
Heartbeat you can avoid the loop, tick, and wait (wait only delays for a minimum of ~0.03 seconds by default anyway, anything lower gets capped). When you open connections in a local scope in a permanent script you need to remember to disconnect them. Using a player unique debounce lets multiple players run in the same script, but depending on what your game is, that may or may not be necessary.
[CODE lang="lua" title="Timer Thing"]-- i just used these for testing
local startPart, endPart = workspace:WaitForChild('Start'), workspace:WaitForChild('End')
-- services
local players = game:GetService('Players')
local runService = game:GetService('RunService')
local running = {} -- player unique debounce
local function StartTimer(player)
local timeTaken = 0
local runConnection
local touchedConnection
runConnection = runService.Heartbeat:Connect(function(step)
if not players:FindFirstChild(player.Name) then
runConnection

isconnect() -- player no longer exists, disconnect to prevent memory leaks
touchedConnection

isconnect()
end
-- increment by step (time since last heartbeat)
timeTaken += step
-- format to MM:SS:MsMsMs
local playerTime = string.format("%02d:%02d:%03d", timeTaken/60%60, timeTaken%60, timeTaken%1*1000)
-- i just used a print to not make a gui
print(player.Name .. ' - ' .. playerTime)
end)
--
touchedConnection = endPart.Touched:Connect(function(part)
local playerTouched = players:GetPlayerFromCharacter(part:FindFirstAncestorOfClass('Model'))
if playerTouched ~= player then return end -- either isn't a player or not the right player
runConnection

isconnect() -- player finished, disconnect heartbeat counter
touchedConnection

isconnect()
running[player.UserId] = nil -- ends player unique debounce so they can start again
end)
end
startPart.Touched:Connect(function(part)
local player = players:GetPlayerFromCharacter(part:FindFirstAncestorOfClass('Model'))
if not player then return end -- touched part wasn't a player
if running[player.UserId] then return end -- player already started
running[player.UserId] = true
StartTimer(player)
end)
players.PlayerRemoving:Connect(function(player)
running[player.UserId] = nil -- remove player from dictionary if they leave
end)[/CODE]