RunService and Lerp problem

ok then, fix the code to this

    local steps = 0
    local a = 0
	while steps < 10 do
		
		task.wait()
        a += 0.1
        steps += 1
		part.CFrame = originCF:Lerp(target1.CFrame, a)
	end

If I’m correct, this should get rid of the error because we now use steps (an integer) to check, there should be no floating point precision issue

2 Likes

Oh yeah that makes sense so like 1 to 10, let me test that out.

1 Like

Worked just perfectly, thanks. Anyway I was wondering if that would somehow leak memory because we set values to the variables frequently.

1 Like

somehow leak memory because we set values to the variables frequently.

Once you get out of a scope, the variables within that scope is garbage collected, so there’d be no memory leak.

Also now that it works fine, you can go back to using RunService.HeartBeat with the same idea in mind

The layout should look this:

local RunService = game:GetService("RunService")

local cdCon cdCon = clickDetector.MouseClick:Connect(function(plr)
  cdCon:Disconnect() -- Make sure player can't click again
  local timePassed = 0
  local totalTime = 5 -- seconds
  local intialCF = part.CFrame

  local con con = RunService.Heartbeat:Connect(function(dt)
     timePassed += dt
     local alpha = math.min(timePassed/totalTime, 1) -- Make sure it doesn't go beyond 1
     part.CFrame = initialCF:Lerp(target1.CFrame, alpha)
     if timePassed >= totalTime then con:Disconnect() end
  end)
end)

Edit: fixed local alpha = math.max(timePassed/totalTime, 1)
To: local alpha = math.min(timePassed/totalTime, 1)

2 Likes

Try this:

local lerpTime = 10
local elapsedTime = 0
local originalCFrame = part.CFrame

while elapsedTime < lerpTime do
    elapsedTime += RunService.Heartbeat:Wait()
    part.CFrame = originalCFrame:Lerp(bruh.CFrame, elaspedTime / lerpTime)
end
1 Like

I still don’t know how the heck this gets printed out.

1 Like

I still don’t know how the heck this gets printed out.

Like I mentioned, floating-point precision.
The computer can’t actually store 0.1 normally, it stores it like 0.10000000000000000782378

2 Likes

Btw, is this a typo or it is meant to be like this? if so, why?

1 Like

It is meant to be like that, otherwise you can’t access cdCon inside the function of the clickDetector

1 Like

why is there two cdCon tho? As far as I know one is enough

1 Like

It’s more of a coding style I’ve developed, if you write it normally it’d look like this

local cdCon 
cdCon = clickDetector.MouseClick:Connect(function(plr)
  -- code
end)
2 Likes

And if like there is a number 0.9999999999999, the script rounds it up? that’s the alpha value in your code printed out before disconnecting in the while loop.

1 Like

And if like there is a number 0.9999999999999, the script round it up? that’s what the alpha in your code printed out before disconnecting in the while loop.

No, it is exactly like that. The statement of the while loop was a < 1
And 0.9999999999999 is definitely < 1

1 Like

I mean, I thought like to do a full lerp the alpha has to be 1. No?

1 Like

I mean, I thought like to do a full lerp the alpha have to be 1. No?

Yes, but in this case 0.9999999999999999 and 1 is close enough to not make a difference, like you definitely can’t tell whether it is misplaced by 0.0000000001 studs or not.

1 Like

Oh ok, thanks. Because like the part is now positioned right exactly in where it’s suppose to. But like the alpha being 1.0111 will move the part slightly?

1 Like

It can’t possibly be 1.0111, that’s too much of a floating-point precision error. At most it would be at least like 12 0s before getting a different number

2 Likes

Edit: Typo in example script

Just to note:
In Lua, all numbers are stored and considered as the double type - you can read more about that here.

You’re always going to have funky numbers when using a double or float because of floating point precision errors - read about the limitations here.

The following won’t help with the inherent issues and limitations of floating point arithmetic, but to answer some of your questions:

  1. Just clamp the value if you’re worried alpha will somehow be greater than 1 or less than 0, e.g.:
local alpha = runningTime / lerpTime
alpha = math.clamp(alpha, 0, 1)
  1. If you’re worried about alpha not resolving to 1 at the end, you can either (a) check if it fuzzy equals 1 then bump the value, and/or (b) setting the CFrame of the part after the interpolation has finished, e.g.:
-- constants
local EPSILON = 1e-4
local LERP_TIME = 10

-- set up
local RunService = game:GetService('RunService')
local part = script.Parent
local clickDetector = part:WaitForChild('ClickDetector')
local targets = workspace:WaitForChild('Targets')
local target1 = targets:WaitForChild('1')

-- checks if two numbers are approximately equal to each other
local function doesFuzzyEqual(a, b, threshold)
	threshold = threshold or EPSILON
	return a == b or math.abs(a - b) <= (math.abs(a) + 1) * threshold
end

-- the click event handler & interpolation
local clickConnection
clickConnection = clickDetector.MouseClick:Connect(function (player)
	clickConnection:Disconnect()

	local runningTime = 0
	local originCFrame = part.CFrame
	local targetCFrame = target1.CFrame

	local runtimeConnection
	runtimeConnection = RunService.Stepped:Connect(function (gameTime, deltaTime)
		-- calculate the interpolation alpha
		local alpha = runningTime / LERP_TIME

		-- e.g. if the number is 0.9999 or 1.0001
		if doesFuzzyEqual(alpha, 1) then
			-- e.g. set the alpha to 1 since you were worried it would be slightly below / above the final value
			alpha = 1
		end

		-- clamp the value to ensure it's between between 0 and 1
		alpha = math.clamp(alpha, 0, 1)

		-- update the part's CFrame
		part.CFrame = originCFrame:Lerp(targetCFrame, alpha)

		-- disconnect if the alpha has reached its maximum
		if alpha >= 1 then
			-- since you're worried the part's CFrame won't be the target's CFrame exactly, let's update it now...
			part.CFrame = targetCFrame

			-- now let's disconnect our runtime since we're finished
			return runtimeConnection:Disconnect()
		end

		-- increase our elapsed time
		runningTime += deltaTime
	end)
end)
2 Likes

Yeah I think math.clamp() works pretty good.

Also, I don’t really know if there is a solution to not increase the activity rate for scripts that uses RunService. For game performance.