How to fix this timer?

Hello developers,

I made a speedrun for my obby game, it works but there is a problem if player is laggy or slow internet then the timer is also laggy along with him and its not being fair for other speed runners, as they don’t lag so their timer is correct and others are wrong, is there any way to fix this, the script is in a local script

show me your code that I can see some errors

2 Likes

You should calculate in the server cause exploiters and use os.clock() as an accurate timer.

1 Like

Use RemoteEvents for each timer - exploiters cannot change the time and laggy people will have the same time.

1 Like

How will the remote event know when to end speed run, i mean the server side script

the script:

local seconds = 0
local mins = 0
local starttimer = false
local canwork = true
local overallseconds = 0
local hours = 0
local target = 0
local currentstage = 1
local currentdifficulty = 1

game.ReplicatedStorage.UpdateStage.OnClientEvent:Connect(function(number)
    if tonumber(number) == tonumber(target) then
        starttimer = false
        if target == 21 then
            game.Players.LocalPlayer.Character.HumanoidRootPart.CFrame = game.Workspace.Checkpoint:FindFirstChild("1").CFrame + Vector3.new(0,5,0)
        elseif target == 40 then
            game.Players.LocalPlayer.Character.HumanoidRootPart.CFrame = game.Workspace.Checkpoint:FindFirstChild("21").CFrame + Vector3.new(0,5,0)
        elseif target == 60 then
            game.Players.LocalPlayer.Character.HumanoidRootPart.CFrame = game.Workspace.Checkpoint:FindFirstChild("40").CFrame + Vector3.new(0,5,0)
        end
        script.Parent.Text = "Speedrun completed! Time: "..mins..":"..seconds
        target = 0
        game.StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType.Chat,true)
        wait(2)
        script.Parent.Visible = false
        script.Parent.Parent.Parent.IsReplaying.Value = false
        game.ReplicatedStorage.SaveSpeedRunEvent:FireServer(currentdifficulty,seconds)
    end
end)

game.ReplicatedStorage.ToggleSpeedrunEvent.OnClientEvent:Connect(function(difficultynumber)
    script.Parent.Visible = true
    overallseconds = 0
    seconds = 0
    mins = 0
    hours = 0
    if difficultynumber == 1 then
        game.Players.LocalPlayer.Character.HumanoidRootPart.CFrame = game.Workspace.Checkpoint:FindFirstChild("1").CFrame + Vector3.new(0,5,0)
        target = 21
        currentdifficulty = 1
    elseif difficultynumber == 2 then
        currentdifficulty = 2
        game.Players.LocalPlayer.Character.HumanoidRootPart.CFrame = game.Workspace.Checkpoint:FindFirstChild("21").CFrame + Vector3.new(0,5,0)
        target = 40
    elseif difficultynumber == 3 then
        currentdifficulty = 3
        game.Players.LocalPlayer.Character.HumanoidRootPart.CFrame = game.Workspace.Checkpoint:FindFirstChild("40").CFrame + Vector3.new(0,5,0)
        target = 60
    end
    script.Parent.Text = "You need to reach the next difficuty"
    game.Players.LocalPlayer.Character.HumanoidRootPart.Anchored = true
    wait(2)
    script.Parent.Text = "You cannot chat during speed run"
    wait(1.5)
    script.Parent.Text = "Good luck!"
    wait(1.5)
    script.Parent.Text = "3"
    wait(1)
    script.Parent.Text = "2"
    wait(1)
    script.Parent.Text = "1"
    wait(1)
    script.Parent.Text = "Go!"
    starttimer = true
    game.StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType.Chat,false)
    game.Players.LocalPlayer.Character.HumanoidRootPart.Anchored = false
    script.Parent.Parent.Parent:FindFirstChild("IsReplaying").Value = true
end)


while wait(0.5) do
    if starttimer == true then
        if starttimer == true and target ~= 0 then
            if seconds >= 59 then
                seconds = 0
                mins = mins + 1
                overallseconds = overallseconds + 0.5
            else
                seconds = seconds + 0.5
                overallseconds = overallseconds + 0.5
            end
            script.Parent.Text = hours..":"..mins..":"..seconds
        end
    end
end

here difficulties means each difficulty, as its a difficulty chart obby you can do any difficulty speedrun like speedrun easy difficulty.Like that

can you set os.time() as starting time and then calculate? or use tick()

You should not use wait(.5) as a clock. Use tick() or something accurate. Wait(seconds) is not guaranteed, as you have found out the hard way.

1 Like

yes now i used tick but uh how do i make the timer to seconds,mins and hours?

sample tick again at the end and subtract, that gives you seconds elapsed. divide that to get minutes or hours etc.

1 Like

like this i guess
the script:

while wait(0.5) do
    if starttimer == true then
        if starttimer == true and target ~= 0 then
            overallseconds = tick() - startingtime
            seconds = string.sub(tostring(overallseconds),#tostring(overallseconds) - 1,#tostring(overallseconds))
            script.Parent.Text = hours..":"..mins..":"..seconds
        end
    end
end

is it correct? the script one or wrong

You should fire a function when the player finishes instead of a loop.

1 Like

then how can u make a timer without loop

the format is this maybe

local Minutes = (Seconds - Seconds%60)/60
	Seconds = Seconds - Minutes*60
	local Hours = (Minutes - Minutes%60)/60
	Minutes = Minutes - Hours*60
end)

tick() does it for you it’s a universal timer.

1 Like

yes i mean like the player may lag but the starting time won’t change so the timer works according to starting time only right

I don’t think that is a good way to do it. I don’t think you need this while loop at all. You know when the race starts, you know when it ends, why do you need to loop and wait for this?

when the race starts: starttime = tick()
when the race is done: elapsedtime = tick() - starttime

then you can find hours, minutes, seconds based on the number of seconds you have in elapsedtime

1 Like

yes and the timer is elapsed time and thats why its looped

Right but you don’t need a loop to do that, you capture the start time, then subtract it from the end time.

Your loop could waste up to .5 seconds before it figures out starttimer == false

1 Like