So my problem is, I have a train which moves from one “node” to the next, these nodes contain among other things a CFrame and a Speed which the train needs to reach when it has reached the node.
The train already works fine, I use lerp, the delta being the time from one node to the other, however that way the speed changes instantaneously, I want smooth acceleration, deceleration without adding 1000 nodes.
I have no idea how to re-script the new lerping function using acceleration because the time it takes to reach the next node changes because the speed does too.
Start = function(cart, journey, pref)
local speed = 0
cart:SetPrimaryPartCFrame(journey[1])
for i = 2, #journey do
--speed starts at 0
--journey[i] contains .Node as CFrame and .Speed as number
--journey[i] is the next node, journey[i-1] the current one
local distance, duration = module.GetDistanceDelta(
journey[i-1],journey[i]
)
if journey[i].Speed > journey[i-1].Speed then
local acceleration = (math.pow(journey[i-1].Speed, 2) - math.pow(journey[i].Speed, 2)) / (2 * distance)
speed = speed + acceleration
print("Acceleration of ", pref.LineName," ", acceleration)
else
local deceleration = math.pow(journey[i].Speed, 2) - math.pow(journey[i-1].Speed, 2) / (2 * distance)
speed = speed - deceleration
print("Deceleration ", pref.LineName, " ", deceleration)
end
--lerping happens below
local start = journey[i-1].Node
local spent = 0
while spent < 1 do
spent = spent + runService.RenderStepped:wait() / duration
cart:SetPrimaryPartCFrame(start:lerp(journey[i].Node, spent))
end
cart:SetPrimaryPartCFrame(journey[i].Node)
end
end
Just for reference, this would replace the code below your comment, lerping happens below. All you have to do is define distance and duration correctly.
-- new variable!
local speed = distance / duration
local start = journey[i-1].Node
local spent = 0
while spent < 1 or spent > 0 do -- just in case you want the train to go backwards
local dt = runService.RenderStepped:Wait()
-- using a clamp so that you don't need to SetPrimaryPartCFrame at the end
spent = math.clamp(spent + speed * dt, 0, 1)
-- use this space to calculate a new speed,
-- especially if you want it to decelerate or accelerate mid-loop
cart:SetPrimaryPartCFrame(start:Lerp(journey[i].Node, spent))
end
-- no need for SetPrimaryPartCFrame here, the while loop covers it!
-- continue on with the rest of your code...
I also made a cool node pather here, if that helps. Pay attention to the GrindRail function, especially the RunService.RenderStepped connection I make in it. This was a solution for rail grinding, but trains also ride on rails, so you can use the same concept: