I would say I was pretty close to finishing the logic of all of that, but I have come to the strange wall that makes me think that unfortunately there is a bug / bugs here. But I donât know, maybe someone can fully finish my logic.
My assumption #1: No, PostSimulation and Heartbeat are different things and I will explain why you can think that they are in fact the same thing, but I want to say that graph from docs is correct but there are still some missing parts.
My assumption #2: Yes, you are right. Heartbeat and task.wait() have some differencies.
Here is again the code that we will use:
Also we will again use the graph from the site:
--!strict
local RunService = game:GetService("RunService")
RunService.PreRender:Connect(function()
print("PreRender")
task.defer(function()
print("Deferred PreRender")
end)
end)
RunService.PreAnimation:Connect(function()
print("PreAnimation")
task.defer(function()
print("Deferred PreAnimation")
end)
end)
RunService.PreSimulation:Connect(function()
print("PreSimulation")
task.defer(function()
print("Deferred PreSimulation")
end)
end)
RunService.PostSimulation:Connect(function()
print("PostSimulation")
task.defer(function()
print("Deferred PostSimulation")
end)
end)
RunService.Heartbeat:Connect(function()
print("Heartbeat")
task.defer(function()
print("Deferred Heartbeat")
end)
end)
while true do
task.wait()
print("Loop!")
task.defer(function()
print("Deferred loop!")
end)
end
Letâs test in Immediate mode.
14:48:28.990 PreRender - Client - LocalScript:7
14:48:28.992 Deferred PreRender - Client - LocalScript:9
14:48:29.072 PreAnimation - Client - LocalScript:15
14:48:29.072 Deferred PreAnimation - Client - LocalScript:17
14:48:29.072 PreSimulation - Client - LocalScript:23
14:48:29.072 Deferred PreSimulation - Client - LocalScript:25
14:48:29.073 PostSimulation - Client - LocalScript:31
14:48:29.073 Loop! - Client - LocalScript:50
14:48:29.090 Heartbeat - Client - LocalScript:39
14:48:29.090 Deferred PostSimulation - Client - LocalScript:33
14:48:29.090 Deferred loop! - Client - LocalScript:52
14:48:29.090 Deferred Heartbeat - Client - LocalScript:41
Letâs now donât focus on Deferred loop!, Deferred PostSimulation, Deferred Heartbeat.
As we can see, as documentation said, we have PostSimulation â Loop (âQueue Delayed Scriptsâ) â Heartbeat. Everything seems to work fine.
Letâs switch to Deferred mode:
14:52:02.357 PreRender - Client - LocalScript:7
14:52:02.357 Deferred PreRender - Client - LocalScript:9
14:52:02.717 PreAnimation - Client - LocalScript:15
14:52:02.717 Deferred PreAnimation - Client - LocalScript:17
14:52:02.717 PreSimulation - Client - LocalScript:23
14:52:02.718 Deferred PreSimulation - Client - LocalScript:25
14:52:02.718 Loop! - Client - LocalScript:50
14:52:02.752 PostSimulation - Client - LocalScript:31
14:52:02.752 Deferred loop! - Client - LocalScript:52
14:52:02.753 Heartbeat - Client - LocalScript:39
14:52:02.753 Deferred PostSimulation - Client - LocalScript:33
14:52:02.753 Deferred Heartbeat - Client - LocalScript:41
Now you can think: hm, PostSimulation and Heartbeat are the same things.
But what happens in fact? Letâs not forget that handlers in Deferred mode are executed on invocation points. Here is a list of this points that Roblox have provided here: [Beta] Deferred Lua Event Handling.
RenderStepped
Waiting script resumption (e.g. wait, spawn, delay)
Stepped
Heartbeat
BindToClose
Here where this realisation comes: yes, PostSimulation happens before âQueue Delayed Scriptsâ, as we saw in Immediate mode. And even now it happened before. But PostSimulation is not invocation point. Thatâs why connected function to PostSimulation was called only after âLoop!â was printed. Itâs because while true loop was resumed through task.wait() so it is Waiting script resumption invocation point, so our queue of callbacks had inside of it function that should print PostSimulation. After that we, as graph suggested, go to Heartbeat.
But the problem is that I am not able to understand the order of task.defer() unfortunately since there is no description of term âend of resume pointâ which is used in docs in description of task.defer(). It is reasonable to say that resume points are âInput Eventsâ are fired, callbacks are executed; âPreRender Eventâ is fired, callbacks are executed and so on but unfortunately this logic doesnât work when it comes to âQueue Delayed Scriptsâ, Heartbeat and PostSimulation so I donât know.