The Timer
script allows execution of code at specified time intervals.
The two key methods to use with Timer
are:
-
Timer.SetTimeout(func, delay, ...)
: Executes a function, after waiting a specified number of milliseconds. -
Timer.SetInterval(func, delay, ...)
: Same asSetTimeout()
, but repeats the execution of the function continuously.
Installation
Create a ModuleScript with the name Timer
in ReplicatedStorage and paste the content below
--[[
Timer.lua
Utilities for working with scheduled tasks and time
by @nidorx <Alex Rodin>
]]
local RunService = game:GetService("RunService")
local ID = 1
local TASKS = {}
local MAX_CALLS = 30 -- Allows you to define a limit of executions in each interaction
-- max safe int (int53)
local MAX_SAFE_INT = 9007199254740991 -- (2^53) -1
--[[
Run scheduled tasks.
Perform a non-blocking run using coroutines
]]
RunService.Heartbeat:Connect(function(dt)
local toRemove = {}
local count = 0
for i, task in ipairs(TASKS) do
if not task.IsRunning then
task.Elapsed = task.Elapsed + dt * 1000
if task.Elapsed >= task.Interval then
task.Elapsed = task.Elapsed - task.Interval
-- remove when timeout (runs only once)
if task.IsTimeout then
table.insert(toRemove, task)
end
-- run task
coroutine.wrap(task.SafeExec)()
count = count + 1
-- limit interactions
if count > MAX_CALLS then
break
end
end
end
end
for _, task in ipairs(toRemove) do
local pos = table.find(TASKS, task)
if pos ~= nil then
table.remove(TASKS, pos)
end
end
end)
--[[
Schedule a task for future execution
]]
local function createTimer(func, delay, isTimeout, arguments)
local id = ID
ID = ID + 1
if delay == nil or delay < 0 then
delay = 0
end
if type(delay) ~= 'number' then
error('Number is expected for interval/delay')
end
delay = math.min(MAX_SAFE_INT, delay)
local task = {}
task.Id = id
-- generates a safe execution of the task
task.SafeExec = function()
task.IsRunning = true
local success, err = pcall(func, table.unpack(arguments))
task.IsRunning = false
task.Elapsed = 0
if not success then
warn(err)
end
end
task.IsTimeout = isTimeout
task.Elapsed = 0
task.Init = os.clock()
task.Interval = delay
table.insert(TASKS, task)
return id
end
local Timer = {}
--[[
Repeatedly calls a function, with a fixed time delay between each call. It returns an interval ID which uniquely
identifies the interval, so you can remove it later by calling Timer.Clear(intervalID).
Important! The interval for the next execution of the task only starts to count when the current execution ends,
therefore, a task, even if it takes time, is never executed more than once in parallel
@see https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setInterval
@param func (function) A function to be executed every delay milliseconds (1000ms = 1second).
@param delay (number) The time, in milliseconds (thousandths of a second), the timer should delay in between
executions of the specified function
@param args (...) Additional arguments which are passed through to the function specified by func once the
timer expires
@return intervalID The returned intervalID is a numeric, non-zero value which identifies the timer created by
the call to Timer.SetInterval(); this value can be passed to Timer.Clear(intervalID) to cancel the interval.
]]
function Timer.SetInterval(func, delay, ...)
return createTimer(func, delay, false, {...})
end
--[[
Sets a timer which executes a function once the timer expires.
@param func (function) A function to be executed after the timer expires.
@param delay (number) The time, in milliseconds (thousandths of a second, 1000ms = 1second), the timer should
wait before the specified function or code is executed. If this parameter is omitted,
a value of 0 is used, meaning execute "immediately", or more accurately, the next
RunService.Heartbeat event cycle. Note that in either case, the actual delay may be
longer than intended
@param args (...) Additional arguments which are passed through to the function specified by func.
@return timeoutID The returned timeoutID is a numeric, non-zero value which identifies the timer created by
the call to Timer.SetTimeout(); this value can be passed to Timer.Clear(timeoutID) to cancel the timeout.
]]
function Timer.SetTimeout(func, delay, ...)
return createTimer(func, delay, true, {...})
end
--[[
Used to inactivate schedules created with Timer.SetTimeout or Timer.SetInterval
]]
function Timer.Clear(id)
for pos, task in ipairs(TASKS) do
if task.Id == id then
table.remove(TASKS, pos)
break
end
end
end
return Timer
Timer.SetTimeout
- The
Timer.SetTimeout(func, delay, ...)
method will call a function after the time specified in milliseconds (1000 ms = 1 second) has passed. - The specified function will be executed once. If you need to run a function multiple times, use the
Timer.SetInterval()
method. - To stop the timeout and prevent the function from executing, use the
Timer.Clear(timeoutID)
method. - The
Timer.SetTimeout()
method returns an ID which can be used inTimer.Clear(timeoutID)
method.
Usage and Purpose
Sometimes it is necessary to program a function call in a specific moment. The Timer.SetTimeout()
function is ready to help you with this task-scheduling by postponing the execution of a function until the specified time.
Please bear in mind that the Timer.SetTimeout()
function will execute functions once. If you want the function to be repeated multiple times, you should use Timer.SetInterval()
.
local Timer = require(game.ReplicatedStorage:WaitForChild('Timer'))
local function MyFunction(name)
print("Hello, "..name)
end
Timer.SetTimeout(MyFunction, 3000, "Alex")
Timer.SetTimeout(MyFunction, 6000, "John")
Syntax
As you can see in the snippet above, the Timer.SetTimeout()
function can contain several parameters:
Timer.SetTimeout(func, delay, param_one, param_two, ...)
First of all, the Timer.SetTimeout()
method should contain the function that you intend to apply. The second parameter sets a time when the specified function is to be called. However, it is optional, and the default value is 0 (meaning execute “immediately”, or more accurately, the next RunService.Heartbeat event cycle). You can also specify parameters for the function you have indicated previously.
Parameter | Description |
---|---|
func |
(Required). Specifies the function that will be executed. |
delay |
(Not required). Specifies the time the function will be executed. 0 milliseconds by default. |
param_one, param_two, ... |
(Not required). Parameters passed to the function. |
Timer.SetInterval
- The
Timer.SetInterval(func, delay, ...)
method executes a specified function multiple times at set time intervals specified in milliseconds (1000ms = 1second). - The
Timer.SetInterval()
method will keep calling the specified function untilTimer.Clear(intervalID)
method is called. - The
Timer.SetInterval()
method returns an ID which can be used by theTimer.Clear(intervalID)
method to stop the interval. - If you only need to execute a function one time, use the
Timer.SetTimeout(func, delay, ...)
method.
Usage of Timer.SetInterval
It could be defined simply as a method which allows you to invoke functions in set intervals.
The Timer.SetInterval()
function is similar to the Timer.SetTimeout()
method. How are they different? Well, Timer.SetTimeout()
calls functions once. However, with the set interval method you can invoke them multiple times.
Let’s say you need to display a message every 3 seconds. By applying the Timer.SetInterval()
function, you will be able to perform this task.
The following code example shows the way the message is set to be displayed every 3 seconds:
Example
local Timer = require(game.ReplicatedStorage:WaitForChild('Timer'))
local count = 0
local param1 = "Hello"
local param2 = "World!"
Timer.SetInterval(function(a, b)
count = count + 1
print(a..", "..b.." Count = "..count)
end, 3000, param1, param2)
Syntax
See the code snippet below. This is the syntax of the function that you should keep in mind:
Timer.SetInterval(func, delay, param_one, param_two, ...)
As you can see, the Timer.SetInterval()
can contain three parameters. The first one identifies which function is going to be applied in the set time intervals. As you might expect, you also should include the milliseconds to set the frequency of your function. Additionally, you can specify parameters for the function to be applied.
Parameter | Description |
---|---|
func |
(Required). Defines the function to run. |
delay |
(Not required, defaults to 0 = RunService.Heartbeat ). Defines how often the function will be executed (in millisecond intervals). |
param_one, param_two, ... |
(Not required). Defines any additional function parameters. |
Stopping the Function
In some cases, you might need to stop SetTimeout()
or SetInterval()
from being executed before the times comes. You’ll need to use the Timer.Clear(id)
method. It’s meant to stop the timer set by using the Timer.Set*()
function.
The Timer.SetTimeout()
and Timer.SetInterval()
returns a variable called ID
. You can then use it to call the Timer.Clear(ID)
function.
Timer.Clear(ID)
itself has no return value: the only result is achieves is making Timer
stop SetTimeout()
or SetInterval()
from running.
Example 1
local Timer = require(game.ReplicatedStorage:WaitForChild('Timer'))
local function MyFunction(name)
print("Hello, "..name)
end
local timeoutId1 = Timer.SetTimeout(MyFunction, 3000, "Alex")
local timeoutId2 = Timer.SetTimeout(MyFunction, 6000, "John")
local timeoutId3 = Timer.SetTimeout(MyFunction, 9000, "Mary")
Timer.Clear(timeoutId1)
Timer.Clear(timeoutId3)
Example 2
local Timer = require(game.ReplicatedStorage:WaitForChild('Timer'))
local count = 0
local param1 = "Hello"
local param2 = "World!"
local intervalId
intervalId = Timer.SetInterval(function(a, b)
count = count + 1
print(a..", "..b.." Count = "..count)
if count > 3 then
print("Bye")
Timer.Clear(intervalId)
end
end, 3000, param1, param2)