Make lerp go faster and smoother, how?

What’s good!
So, I’m having an issue with my lerp function, it’s supposed to lerp a roller coaster cart, here’s what I’ve got:

function lerpRide(cart,node)
	
	for i = 0, 10 do
		local t = i / 10
		local newC = NODES["Node"..node].CFrame
		cart.Cart1.MainPart.CFrame = NODES["Node"..node - 1].CFrame:Lerp(newC,t)
		
		--if i == 900 then
		--	return
		--end
		
		local waitSpeed = cart.CartSpeed.Value / 10
		wait(waitSpeed)
		print(waitSpeed)
	end
end

An issue with it right now, it goes WAY too slow, and it’s to snappy, I have no clue how to make it run smoother and how to make it quicker. Any help would be very very appreciated, thanks!

To make it smooth use TweenService

1 Like

You can try to use task.wait instead, to see if that makes it any smoother.

1 Like

Thanks for the reply!
I’ve previously tried using TweenService, but I need the speed to change during the movement of the cart, And I couldn’t get anything working with it. :1

I will definitely try it! Thanks!

wait() should be good enough, otherwise you can use game:GetService(“RunService”).Heartbeat:Wait()

1 Like

Thanks! I can’t seem to get it working, Is there any other method than lerp or tweening that could provide a good source to use? I’m desperate xD

I’d recommend the pre-physics one in a more “let loose” while loop based system

It works more with the system, using the exact time of the previous frame to determine how far it should go based on that and the speed, not hoping the time will be a specific value and that there’s no lag or any other issues

Runservice also has twice the accuracy as wait() at its best and this system also prevents FPS unlockers from creating ultra speedy trains as funny as that’d be

local rs = game:GetService("RunService")

function lerp(cart,node)
    local prev = --get CFrame of previous mode
    local curr = --get CFrame of current node
    local distance = (prev.p-curr.p).Magnitude
    local d = 0
    while d <= distance do
        cart.CFrame = prev:Lerp(curr, d/distance)
        local dt = rs.Stepped:Wait()
        d = d + cart.CartSpeed.Value * dt
    end
    cart.CFrame = curr
end

This should function fairly similar to your current one and you can change the speed whenever you so desire
It’s probably not set up exactly how you’d want it to be so you’ll prob have to do some manual editing, but all of the math is there

There’s one disbenefit to this exact setup, on the very last frame before the cart reaches the node, the train does not move its actual speed for that last 60th of a second
A simple way to fix this would be to return the “excess” distance and simply add it onto d for the next node

For example:

local rs = game:GetService("RunService")

function lerp(cart,node,leftovers)
    local prev = --get CFrame of previous mode
    local curr = --get CFrame of current node
    local distance = (prev.p-curr.p).Magnitude
    local d = leftovers
    while d <= distance do
        cart.CFrame = prev:Lerp(curr, d/distance)
        local dt = rs.Stepped:Wait()
        d = d + cart.CartSpeed.Value * dt
    end
    return d-distance
end

KEEP IN MIND that this has to be set up in the code where you run the lerp function, in a way similar to this, but it doesn’t have to be exact:

local leftovers = 0
for node = 1, #NODES do --just guessing smthn random
    leftovers = lerp(cart, node, leftovers)
end

Again it doesn’t have to be exactly this, just along the lines of this so that the return value of the previous function gets passed on to the following function

Also make sure none of the nodes are the same exact position it’ll break it

7 Likes

Thank you so much man! I’ll 100% try it out when I can!

EDIT: It works perfectly! Thank you for taking the time to describe it to me in detail, I would’ve given up if you hadn’t of commented, Thank you so much!!!

Small issue, It seems that the cart speeds up over time, Any idea why? (My code is down below.)
https://gyazo.com/b4436dc8f6217f08ef3d85d286853aa5

local rs = game:GetService("RunService")

local NODES = workspace.CoasterSystem.Nodes:GetChildren()

local StartNode = 5
local CurrentNode = StartNode


function lerp(cart,node,leftovers)
	
	local prev1 = workspace.CoasterSystem.Nodes["Node"..node - 1].CFrame
	local curr1 = workspace.CoasterSystem.Nodes["Node"..node].CFrame
	local distance = (prev1.p-curr1.p).Magnitude
	
--	local prev2 = workspace.CoasterSystem.Nodes["Node"..node - 3].CFrame
--	local curr2 = workspace.CoasterSystem.Nodes["Node"..node - 2].CFrame
	
	local d = leftovers
	while d <= distance do
		
		cart.Cart1.MainPart.CFrame = prev1:Lerp(curr1, d/distance)
		--cart.Cart2.MainPart.CFrame = prev2:Lerp(curr2, d/distance)
		
		local dt = rs.Stepped:Wait()
		d = d + (cart.CartSpeed.Value / 4) * dt
	end
	return d-distance
end


while wait() do
	
	local leftovers = 0
	for node = 1, #NODES do
		local cart = workspace.CoasterSystem.Ride1
	
		if workspace.CoasterSystem.Nodes:FindFirstChild("Node"..node) then
			leftovers = lerp(cart, node, leftovers)
			CurrentNode += 1
		else
			CurrentNode = StartNode
		end
	end

end

Thank you again!

How are you determining cart.CartSpeed.Value?
Doing some basic testing outside of studio your current script seems to work, maybe theres some nasty interaction between how youre determining your speed and this new script

That’s so odd, I’m changing the speed to one value (0.5), And it still speeds up… I’m using the script in starterGui currently.

Try printing out:

  1. speed
  2. speed * dt
  3. leftovers

Ill respond to you tomorrow when I can!! Thanks!

1 Like

Here’s what the print window looks like:

It does look like it’s speeding up, any idea why?

Recreating it in studio, it doesnt seem to speed up at all

Your example is also way too fast if the speed is only 0.1, it should be going very slow at that speed

Would it be possible for you to send your basic setup and script?

1 Like

Here’s the full script in starterGui:

local rs = game:GetService("RunService")

local NODES = workspace.CoasterSystem.Nodes:GetChildren()

local StartNode = 5
local CurrentNode = StartNode


function lerp(cart,node,leftovers)
	local NodePath = workspace.CoasterSystem.Nodes
	local prev = NodePath["Node"..node - 1].CFrame
	local curr = NodePath["Node"..node].CFrame
	local distance = (prev.p-curr.p).Magnitude
	local d = leftovers
	
	while d <= distance do
		cart.Cart1.MainPart.CFrame = prev:Lerp(curr, d/distance)
		local dt = rs.Stepped:Wait()
		d = d + cart.CartSpeed.Value * dt
	end
	
	print("========PRINT WINDOW========")
	local dt = rs.Stepped:Wait()
	print(cart.CartSpeed.Value)
	print(cart.CartSpeed.Value * dt)
	print(leftovers)
	print("============================")
	print(" ")
	
	return d-distance
end


while wait() do

	local leftovers = 0
	for node = 1, #NODES do
		if workspace.CoasterSystem.Nodes:FindFirstChild("Node"..node + 1) then
			local cart = workspace.CoasterSystem.Ride1
			leftovers = lerp(cart, node, leftovers)
		else
			break
		end
	end
	
end

And here’s my explorer window:

Thank you so much for the help so far! I really appreciate it!

(Sorry for the wait, my studio hasnt been working probably because of bloxburg v5282 with 400k players)

Ok Ive been able to recreate your problem

Im going to blame roblox on this one cause this is just stupid
So let me take you through the runservice events, very basic stuff right?
image
Literally every single one of them, all 7 of them have delta time as the first argument
And guess what .Stepped has as its first argument


So uhhh yeah
Thats nice
(Id like to congratulate roblox for yet another stunning performance, as per usual)
Just change

local dt = rs.Stepped:Wait()

To

local _, dt = rs.Stepped:Wait()
1 Like

Oooooooh! Thank you, That makes way more sense xD
I really appreciate you helping me out with this, So thank you! : D
https://gyazo.com/0a95338893e9ff30e7071e1810013227

1 Like