The following is not related to your question, however it is to your code.
Having an infinite loop with a task.wait() inside is far from precise/accurate when it comes to timing stuff, sometimes it might be a little under a minute and sometimes a little over a minute. While you a lot of times don’t require things to happen with milliseconds precision, sometimes you want to be precise. I personally feel that all games that counts and rewards players every X seconds should be precise.
You can achieve such precision by using RunService, let me show you!
local RunService = game:GetService("RunService")
local total = 0
local speed = 1
RunService.Heartbeat:Connect(function(deltaTime)
total += deltaTime
while total >= speed do
print(os.clock())
total -= speed
end
end)
To start off we declare two variables, one to keep track of the total time, in this case ‘total’, and one for how often we want our code to execute, in this case ‘speed’. The ‘speed’ variable is not required however it makes it faster to change the time in the future if we’d like.
After that, connect a Heartbeat event to a function and add the parameter ‘deltaTime’ (can be named anything but it provides the deltaTime). DeltaTime is amount of elapsed seconds between the previous rendered frame and the current one. If we are running at 60 FPS (frames per second), then our DeltaTime would be 1/60, which is approximately 0.017 seconds, however the FPS is not constant and will fluctuate.
To start of our heartbeat function we want to add out deltaTime to our total time, after that we create a while loop that will run if our total time is greater than or equal to our speed (how often we want to specified code to run).
After that we can add our code to execute, in the example I just print the os.clock() so that you can see how precise this way of looping is. You could do the same thing in a normal while loop with a task.wait() to see how “precise” that one is, the answer would be not very.
Finally we subtract our ‘speed’ from our ‘total’. You might be asking why we’re not setting the ‘total’ to zero, that has to do with our deltaTime. Let us imagine that our ‘total’ is equal to 0.99, if our deltaTime for the upcoming heartbeat is, for instance, 0.018, then our ‘total’ would become 1.008, which is more than our ‘speed’ in the example. If we were to straight up set ‘total’ to zero, then we would miss out on eight whole milliseconds, which will quickly build up when using RunService, resulting in a very non-accurate loop.
EDIT: To clarify “miss out on eight whole milliseconds, which will quickly build up” what I meant was that those milliseconds will shift our loop out of sync as those ms won’t ever be counted towards the total time, meaning that it will take longer that in should to execute the next iteration and so on.
I did not add it in the example but remember to save the RBXScriptConnection that the :Connect() returns and :Disconnect() it when the player leaves. This is because the code in this case runs on server, it won’t automatically be removed when the player leaves, unlike local scripts.