--!strict -- A simple fixed step system scheduler -- Fixed updates can happen multiple times per frame -- Variable updates will happen after all fixed updates complete local FIXED_DELTA = (1 / 60) local MAXIMUM_DELTA = (1 / 5) export type System = { --> variable delta_time update, used for rendering --> blend used for interpolation of simulation state update: ((delta_time: number, blend: number) -> ())?, --> fixed delta_time update, used for simulation fixed_update: ((delta_time: number, frame: number) -> ())?, } local function create(systems: {System}): (number) -> () local frame = 0 local accumulator = 0 return function(delta_time: number) delta_time = math.min(delta_time, MAXIMUM_DELTA) accumulator += delta_time local steps = 0 local previous_frame = frame if (accumulator > 0) then --> typically done with a while accumulator >= fixed_rate but this way is 35x faster steps = accumulator // FIXED_DELTA frame += steps accumulator -= (steps * FIXED_DELTA) end for step = 1, steps do local step_frame = previous_frame + step for _, system in systems do if system.fixed_update == nil then continue end system.fixed_update(FIXED_DELTA, step_frame) end end local blend = accumulator / FIXED_DELTA for _, system in systems do if system.update == nil then continue end system.update(delta_time, blend) end end end return create