I only know about a delay is that you can use it in a function here is an example:
local function myPrintFuction() print("Hello!") end delay(2,myPrintFuction) print("Finish?")
I would really like to know about delay more in depth how can we use it and why do you need 2 arguments on delay function because it requires 2 arguments?
A discussion on the delay
function is really a discussion on thread scheduling. Let's look at an example to see how this works.
Let's say, for example, I need to create a part that only exists temporarily. It might show up after a player touches a part, but it will go away shortly thereafter.
local Trigger = workspace.Trigger Trigger.Touched:Connect(function(part) local NewPart = Instance.new("Part") NewPart.Parent = workspace wait(3) NewPart:Destroy() end)
This is all well and good, until I have to have more code running during the time that the function is waiting those 3 seconds to destroy the part. How do we achieve multiple threads running at once?
There are multiple methods. Probably the most common is the spawn
function. In short, using spawn()
allows you to run code side-by-side with other code in the same script (or as close to side-by-side as possible). Here's an example:
local Trigger = workspace.Trigger Trigger.Touched:Connect(function(part) spawn(function() local NewPart = Instance.new("Part") NewPart.Parent = workspace wait(3) NewPart:Destroy() end) part.Parent:BreakJoints() end)
So what does this mean? It means that the entirety of the code, involving the creation and destruction of the part, will all occur while the script keeps reading. Thus, we won't have to wait 3 seconds before it will run part.Parent:BreakJoints()
. This function can be crucial sometimes!
Of course, you can also utilize Debris to perform the same function, as well as some complex Coroutines, on which, I can't lie, I have no knowledge worth sharing!
Without using any of these methods, calling the wait(3)
would yield the thread, which, like I said, would cause part.Parent:BreakJoints()
to wait 3 seconds before executing. With these functions, though, both threads run close to simultaneously.
Now that you somewhat understand how thread scheduling works, you can understand the delay()
function. It is effectively the same as spawn()
, except it accepts a time argument, which can be helpful when you want to cause that specific function to wait before running, without yielding the thread.
I cannot lie, delay()
and spawn()
seem to have completely interchangeable uses. In fact, I always use spawn()
if needed, rather than delay()
. As you continue coding, however, you'll find more and more situations, in which you need different and more specific functions!
Resources
I love your question!
Anyways, notice how when you delay, it doesn't delay anything that comes after it.
Example:
wait:
print("Start") wait(1) print("End")
delay:
print("Start") delay(1, function() print("Delaying") end) print("End")
Notice how it waits a second before printing end. Wait pretty much delays everything that comes after it, whereas delay immediately prints end but waits a second before printing delaying.
Essentially, if you only want to delay a single object, use delay()
If you want to delay everything, use a wait().
Also, the reason why you use 2 parameters is because you need to enter the amount of time you want to wait, and then what you want to do after the delay.
Unfortunately delay()
has a very misleading name. Both delay()
and spawn()
are Roblox Lua wrappers for coroutines. spawn()
will execute encapsulated function as soon as task scheduler becomes available, while delay()
will execute encapsulated function after given time in seconds (could be slightly longer if the scheduler is busy).
Let me explain a bit about Task Scheduler. Roblox Lua scripts execution is not multi-threaded. That means coroutines are not really executed at the same time. What is really happening is that task scheduler will keep executing only one script / coroutine, until it encounters a yielding function (wait()
in most cases) or script reaches its end. Then it starts to execute another script (resumes script that has yielded enough time).
That is why you should never rely on wait()
for accurate time measurement.
Now going back to delay()
and spawn()
(these are essentially the same, spawn just does not require time to be provided). Those functions create separate coroutines. What that means is essentially whatever is wrapped in coroutine can be treated like separate script. Both main script and coroutine will work independently of each other. Consider this example:
for i = 1, 10 do print(i .. " job started.") delay(5, function() print(i .. " job is halfway done.") wait(5) print(i .. " job ended.") end) wait(1) end
This script will start 10 "jobs", with one second delay. Each job then will be ended after 10 seconds. So we have essentially 10 coroutine scripts and one main script. All will work independently and functions will remember the i
value. They will work at the same time and create new threads for task scheduler. Just like 10 separate scripts,
Just remember that while from user point of view it would seem like they are executed at the same time, it is good to know that in reality task scheduler just keeps switching between them.