The point is, doing wait() manually worse than using tick(), os.time(), or another similar method that’s meant to be used for that, as well as accurately counts the time - free of lag or most problems you could encounter with wait().
Also, it’s not actually waiting for 0.01 seconds to let you know. The fastest you can do with wait() is 0.03, no lower. So it’s not working correctly. I recommend you switch it to an os.time or tick() method instead.
So, if I were to add to add an if statement to the script it doesn’t work. I stated if player.Started.Value == true then the timer would start but it didn’t.
No it does not. You’re not aware that it’s only running at 0.03 seconds, not 0.01? The limitation of wait() is 0.03, which is about 1/30th of a second.
here is a script that will run in the way you wanted it to. It will only give the time if they have started.
local milisecond = 0
local second = 0
local minute = 0
local hour = 0
while wait(0.01) do
if milisecond >= 60 then
milisecond -= 60
second += 1
end
if second >= 60 then
second -= 60
minute += 1
end
if minute >= 60 then
minute -= 60
hour += 1
end
if game.Players.LocalPlayer.Started.Value == true then
milisecond += 1
end
script.Parent.Text = hour..":"..minute..":"..second.."."..milisecond
end
So even though you are defining wait(0.01) its not gonna work at all because the wait() can only go to 0.03 so your script is not gonna work as intended because its gonna run .02 seconds slower than it is meant to. The script may still work because Lua is a forgiving language but your time will always be off. I believe if you change wait to tick() it should fix that problem because the tick() function allows you to start from 0.01.
First of all, you’ll want to count the seconds somehow (duh).
I’d recommend marking a start time with os.clock()
Next you’ll want to figure out how to transform this into your timer. The easiest way to do this is using some modulos and some flooring. I like to define all of my time amounts in variables.
Lastly, you’ll want to make sure each piece of the timer except the first is two digits (which is also pretty easy).
You can update the timer at any time, even randomly if you wanted to, and it’ll accurately measure time.
Here’s a full implementation of this (I really recommend trying to understand it, its better to understand the code than to just use it and not have learned anything!):
local RunService = game:GetService("RunService")
local SECOND = 1
local MINUTE = SECOND * 60
local HOUR = MINUTE * 60
local startTime
local function getTime()
return os.clock()
end
local function readableTime(timer)
-- First of all, get all of the times in their amounts
local remainder = timer -- Basically this is the "not included" time
local hours = math.floor(remainder / HOUR) -- Figure out the number of whole hours
remainder = timer % HOUR -- Update our remainder time
local minutes = math.floor(remainder / MINUTE) -- Figure out the number of whole minutes in the remaining time
remainder = remainder % MINUTE -- Update our remainder time again
local seconds = math.floor(remainder / SECOND) -- Figure out the number of whole seconds in the remaining time
remainder = timer % SECOND
local hundredthsOfASecond = math.floor(remainder * 10^2) / 10^2 -- Take the first two decimal digits
minutes = tostring(minutes)
if #minutes < 2 then -- Make sure the minutes section is two digits, if not, its less than 10, so we can add a 0
minutes = "0"..minutes
end
seconds = tostring(seconds)
if #seconds < 2 then -- Make sure the seconds section is two digits, if not, its less than 10, so we can add a 0
seconds = "0"..seconds
end
hundredthsOfASecond = tostring(hundredthsOfASecond):sub(2) -- Convert the decimal results to a string and remove the first 0
return table.concat({hours, minutes, seconds..hundredthsOfASecond}, ":") -- Concatenate everything with a : in between
end
local function updateTimer()
local currentTime = getTime()
local timer = currentTime - startTime
local timerText = readableTime(timer)
-- Set the timer text
end
local function startTimer() -- Start the timer!
local currentTime = getTime()
if startTime ~= currentTime then
startTime = currentTime
coroutine.wrap(function() -- Create a new thread for the timer to run in
local timerTime = startTime
while timerTime == startTime do -- Make sure the current timer is running
updateTimer()
RunService.Heartbeat:Wait() -- Wait for Heartbeat (Approximately 1/60th of a second)
end
end)()
end
end
local function stopTimer() -- Stop the timer
startTime = 0 -- This causes other timer loops to exit since the timer will check if it has been changed and exit if it has
end
startTimer()
-- Other code
Well, I mean, its up to you how you do it. I’ve simply provided an explanation for how you can accurately track the time that has passed and create a readable time from that (e.g. 1:02:03.28).
You can implement it in its own module, and maybe even make a Timer object so you can use more than one timer at once, or you can use it in its own unique script.
Mhm! It honestly makes sense to me to only include the timer code in local scripts since updating a property like that would replicate each time. If ever you needed to synchronize other player’s timers, you could just send the start time to the client.
You would need to translate the server’s time into the client’s time though, which you could do in a few ways, the easiest of which is just to have the server send the os.clock() result to the client once, and the client can compare its own os.clock() value:
local serverClockTime = getServerClockTimeSomehow()
local clientClockTime = os.clock()
local clockTimeOffset = serverClockTime - clientClockTime
function getTime()
return clockTimeOffset + os.clock()
end
That’s certainly not perfect but the most you’ll end up with is players seeing a slightly delayed timer. You could resynchronize the clocks occasionally if you wanted to, and you can get even more complicated and average a couple of the previous values together when you do that, but, that’s really only if you care.
Another option if you want complete accuracy in a much easier way is to use os.time() rather than os.clock() since it should be synchronized between the client and the server, whereas os.clock() is not synchronized (its the newly added version of tick essentially). The downside to this is you lose out on decimal seconds, but, if you don’t care about this, you don’t care about it.
Hello! So I created a new script, with tick. This is the script, but I don’t know how to make a condition before running the script and how to stop the timer and reset it. Any suggestions? Here is the script…
local start = tick()
while true do
wait()
local diff = tick() - start
local min = math.floor(diff / 60)
local sec = diff - min*60
local mil = math.floor((sec - math.floor(sec)) * 10)
sec = math.floor(sec)
script.Parent.Text = min..":"..sec..":"..mil
end
Well, you can use a function to start the timer. To stop the timer you can just have some condition in the loop, and, you can have a function which causes the timer to stop by changing something. The way I did it in my example script above is by basically seeing if start was still the same, so, if you started a new timer, it’d exit the loop since the start time was different, that way multiple timers wouldn’t run at once. And then to make the timer exit, I just change the start time to 0.
And as you can see in my example code, the way I made the timer run without blocking other code is by putting it in a new thread.
I’d also recommend using os.clock now instead of tick (os.clock is a new function which does almost the same thing, but, when it was implemented Roblox suggested no longer using tick, I’d assume either for performance reasons, or something else)
Mhm, although, its not really required to, if you want to stick with “best practices” like that you can. I personally prefer to just because I end up making a lot of high scale projects.