You’ll have to do it your own way using what is effectively a diet version of RenderStepped and seeing how much time has elapsed.
Hook your script to RenderStepped Heartbeat, and gradually add up the time deltas between each frame until it either meets or exceeds 1/targetFPS. Once you do that, you can pass that cumulative delta into the function you use to update your viewport frame.
Edit: I pressed the post button too early. Here’s a code sample:
local RunService = game:GetService("RunService")
local targetFramerate = 60 -- i assume you'll hook this up later
local cumulativeDelta = 0 -- initializing
localViewportUpdateService = RunService.Heartbeat:Connect(function(step)
cumulativeDelta = cumulativeDelta + step
if cumulativeDelta >= 1/targetFramerate then
updateMyViewportFrame(cumulativeDelta) -- replace this with your function you're using to update your viewport frame! you should already be ingesting a deltatime as is
cumulativeDelta = cumulativeDelta%(1/targetFramerate) -- this is a modulo! if you know basic division, this gets the remainder. effectively we're preserving the amount of time
-- we overshot so we can correctly catch the next "frame". alternatively we can just go back to 0, but that might mean going out of sync
end
end)
local function cleanUpRunServiceConnections() -- run this to clean up after yourself when you no longer need to constantly run this!
localViewportUpdateService:Disconnect()
end
I thoroughly apologize, this code is probably super crusty, but this should give you a general idea on where to get started.