What comes after what? | RunService Events

Right now I’m working on a project where I am researching a CaptureService and I needed precise timings for each event to swap the cameras. Task Schediler didn’t give me the results I wanted.
So I made a benchmark:

Was made with 60 FPS
1 frame delay is 0.016s

  • [24683.2500259] = “BindToRenderStep First”,
  • [24683.2500857] = “BindToRenderStep Input”,
  • [24683.2502127] = “BindToRenderStep Camera”,
  • [24683.2502157] = “BindToRenderStep Character”,
  • [24683.2502174] = “BindToRenderStep Last”,
  • [24683.250224] = “RenderStepped”,
  • [24683.2503551] = “PreRender”,
    –render
  • [24683.2511588] = “PreAnimation”,
  • [24683.2513318] = “Stepped”,
  • [24683.2513551] = “PreSimulation”,
  • [24683.2516096] = “Heartbeat”,
  • [24683.2517498] = “PostSimulation”
    –If the signal behaviour is Deferred, all bindable events are resumed here

[os.clock()] = event_name
and here you don’t have any difference bigger than the frame delay
so the benchmark is precise

Every event executes in order by the time
-event with a smaller number executes before the event with a bigger number

if you want to make it by yourself here’s the code

Lua

--the delay is essential to wait until everything start
task.wait(4);
--compiled with ts
local entries = {}
RunService.PostSimulation:Wait()
RunService:BindToRenderStep("1", Enum.RenderPriority.First.Value, function()
	local _arg0 = os.clock()
	entries[_arg0] = "BindToRenderStep First"
	local _ = entries
        --just to execute once
	RunService:UnbindFromRenderStep("1")
end)
RunService:BindToRenderStep("2", Enum.RenderPriority.Input.Value, function()
	local _arg0 = os.clock()
	entries[_arg0] = "BindToRenderStep Input"
	local _ = entries
	RunService:UnbindFromRenderStep("2")
end)
RunService:BindToRenderStep("3", Enum.RenderPriority.Camera.Value, function()
	local _arg0 = os.clock()
	entries[_arg0] = "BindToRenderStep Camera"
	local _ = entries
	RunService:UnbindFromRenderStep("3")
end)
RunService:BindToRenderStep("4", Enum.RenderPriority.Character.Value, function()
	local _arg0 = os.clock()
	entries[_arg0] = "BindToRenderStep Character"
	local _ = entries
	RunService:UnbindFromRenderStep("4")
end)
RunService:BindToRenderStep("5", Enum.RenderPriority.Last.Value, function()
	local _arg0 = os.clock()
	entries[_arg0] = "BindToRenderStep Last"
	local _ = entries
	RunService:UnbindFromRenderStep("5")
end)
RunService.PreRender:Once(function()
	local _arg0 = os.clock()
	entries[_arg0] = "PreRender"
	return entries
end)
RunService.RenderStepped:Once(function()
	local _arg0 = os.clock()
	entries[_arg0] = "RenderStepped"
	return entries
end)
RunService.PreAnimation:Once(function()
	local _arg0 = os.clock()
	entries[_arg0] = "PreAnimation"
	return entries
end)
RunService.PreSimulation:Once(function()
	local _arg0 = os.clock()
	entries[_arg0] = "PreSimulation"
	return entries
end)
RunService.PostSimulation:Once(function()
	local _arg0 = os.clock()
	entries[_arg0] = "PostSimulation"
	return entries
end)
RunService.Stepped:Once(function()
	local _arg0 = os.clock()
	entries[_arg0] = "Stepped"
	return entries
end)
RunService.Heartbeat:Once(function()
	local _arg0 = os.clock()
	entries[_arg0] = "Heartbeat"
	return entries
end)
task.wait(.5)
print(entries)

TS

task.wait(4);
const entries = new Map<number, string>();
RunService.PostSimulation.Wait();
RunService.BindToRenderStep("1", Enum.RenderPriority.First.Value, () => {
  entries.set(os.clock(), 'BindToRenderStep First'), RunService.UnbindFromRenderStep("1")
});
RunService.BindToRenderStep("2", Enum.RenderPriority.Input.Value, () => {
  entries.set(os.clock(), 'BindToRenderStep Input'), RunService.UnbindFromRenderStep("2")
});
RunService.BindToRenderStep("3", Enum.RenderPriority.Camera.Value, () => {
  entries.set(os.clock(), 'BindToRenderStep Camera'), RunService.UnbindFromRenderStep("3")
});
RunService.BindToRenderStep("4", Enum.RenderPriority.Character.Value, () => {
  entries.set(os.clock(), 'BindToRenderStep Character'), RunService.UnbindFromRenderStep("4")
});
RunService.BindToRenderStep("5", Enum.RenderPriority.Last.Value, () => {
  entries.set(os.clock(), 'BindToRenderStep Last'), RunService.UnbindFromRenderStep("5")
});
RunService.PreRender.Once(() => entries.set(os.clock(), 'PreRender'));
RunService.RenderStepped.Once(() => entries.set(os.clock(), 'RenderStepped'));
RunService.PreAnimation.Once(() => entries.set(os.clock(), 'PreAnimation'));
RunService.PreSimulation.Once(() => entries.set(os.clock(), 'PreSimulation'));
RunService.PostSimulation.Once(() => entries.set(os.clock(), "PostSimulation"));
RunService.Stepped.Once(() => entries.set(os.clock(), 'Stepped'));
RunService.Heartbeat.Once(() => entries.set(os.clock(), 'Heartbeat'));

task.wait(.5);
print(entries);

Why is there a delay with RunService.PostSimulation.Wait();?
Just by experimenting, I found the last event.
To measure everything equally we need to start at the end of the cycle where there are no events left.
If I made an error, please let me know

6 Likes