Lerp problems on low framerate

I am having a few problems with lerping on low framerates which makes the delta overshoot going past 1 and causing problems. The solution I am using right now to avoid this issue breaking things is to clamp the alpha from 0 to 1 but I would like to know if there is a better solution to this.

Here is some example code of changing the parts size by lerping it based on a Goal variable.

local RunService = game:GetService("RunService")

local Goal = 1
local Example1 = workspace:WaitForChild("Part")

RunService.RenderStepped:Connect(function(delta)
	Example1.Size = Example1.Size:Lerp(Vector3.one * Goal, 0.25 * delta * 60)
end)

while true do
	Goal = 2
	task.wait(2)
	Goal = 0.5
	task.wait(2)
end

This is an example of what it looks like on different framerates.

(Overshoot example on 10 FPS)
image

Simply use clamping?
Isn’t it simplier idea

Value = math.clamp(LerpedValue, 0, 1)

I would like a better solution if it exists as I am already using clamping.

Clamping won’t matter at the goal you are trying to achieve because in the end, the lerp will still go over it.

As for a solution, why not try lerping the individual x y z values of the vector3, that way you can clamp them separately?

I did notice however you are setting just one value so no need to declare 3 variables.

local rs = game:GetService'RunService'

local newsize = 1
local part = workspace:WaitForChild'Part'

local function lerp(a,b,t)
    return a + (b-a) * t
end

rs.RenderStepped:Connect(function(dt)
    local currSize = part.Size.X -- for now we are using one variable as the y and z are the same
    local scale = math.clamp(lerp(currSize,newsize,0.25*delta*60),0.5,2) -- change 0.5 and 2 to the min and max you want
    part.Size = Vector3.new(scale,scale,scale)
end)

while true do
	newsize = 2
	task.wait(2)
	newsize = 0.5
	task.wait(2)
end
1 Like

This happends because you’re using while loop with task.wait. To fix this you shall calculate estimated time, better with TweenService:GetValue (if you want it to act with tween styles and directions)

Look at this tutorial: What does game:GetService('TweenService'):GetValue(); do? - #2 by Soliform

1 Like

This isn’t a desired solution as the size could change at any point in time and I want to apply this to most of my lerps to make sure they work on all framerates.

First of all, the while loop is to change the size value as an example, second of all I do not want to rely on TweenService as I do not think it is the best solution here.

Have you tried it? Do you understand that the reason why the part’s size is bouncing because the multipliers you applied are going over your desired result in the lerp?

Roblox’s vanilla :Lerp function doesn’t clamp the value returned.

1 Like

I can achieve the same result by replacing

Example1.Size = Example1.Size:Lerp(Vector3.one * Goal, 0.25 * delta * 60)

with

Example1.Size = Example1.Size:Lerp(Vector3.one * Goal, math.clamp(0.25 * delta * 60, 0, 1))

This is not the desired solution I want as I have said before I do not want to clamp it. If there is no other solution I will clamp it if I must.

this is so called “cratch”, it’s a quick solution for problems which later causes more problems.

Could you please elaborate on what you mean by this?

using while loop with task.wait function calls = quick but bad solution which causes glithes right now, you should get rid of them and use method I suggested to you.

Oh my bad, didn’t see that workaround. I don’t think the problem is the lerp then, I think it is either the step connection you’re using or just an artifact of low framerate (it’s common trust me).

They did release new step connections a while ago called PreSimulation and PreRender of RunService which is meant to be more faster than RenderStepped. I suggest you try those.

1 Like

I am only using the while loop for an example to showcase the problem I am having with lerping, I am not using it in an actual game.

while loop — is the source of your problem

A while loop + task.wait isn’t bad, and cannot cause glitches. He’s using it perfectly fine as how it should. Your analogy doesn’t make sense.

Also your GetValue solution doesn’t fit OP’s request because it’s practically the same as clamping alpha and isn’t what OP wanted.

1 Like

The while loop is not the problem. If it was the problem then I wouldn’t be making this post as I don’t use while loops.


The documentation says it is equivalent to PreRender, and I also have tried to use a BindToRenderStep as that is what I use in my game and the same problem still occurs.

I always do this:

math.min(1, dt * 24)

This ensures there won’t be an overshoot.

1 Like

This is still kind of a clamp but it is a faster way to clamp the number to 1, if I can’t find a solution I will just stick to using this.