Greetings!
I am currently making a train system using linear interpolation (lerp). These trains consist of several cars, which are models with primary parts. FirstCar/FIrstTrain indicates the first car in the consist. Here is the folder tree for a train:
The way that waypoints work is there are different lines with different sections. Each section has waypoints. The car passes through a section before moving on to another.
["Testing_Line"] = {"Testing_S1", "Testing_S2", "Testing_Station"}
I currently want the cars to slow down gradually like real trains do.
Now the issue is that the train does not really “Slow down”. Here is what’s happening:
Here is the code that controls the train:
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local LineRoute = require(ReplicatedStorage:WaitForChild("Modules"):WaitForChild("LineRoute"))
local Events = script.Parent.Parent.Events
local TrainFinishEvent = Events.TrainFinish
local TrainController = {}
local timeToReachEndPassed = false
-- Helper Functions
local function Countdown(seconds)
task.wait(seconds)
print("supposed to stop")
timeToReachEndPassed = true
end
-- Function to sort waypoints numerically
function TrainController.sortWaypoints(waypoints)
table.sort(waypoints, function(a, b)
return tonumber(a.Name:match("%d+")) < tonumber(b.Name:match("%d+"))
end)
return waypoints
end
-- Function to slow down a train
function TrainController.AdjustThrottle(train, targetThrottle, duration)
local throttleObject = train.Parent.Parent:FindFirstChild("Throttle")
if not throttleObject then return end
local startThrottle = throttleObject.Value
local delta = targetThrottle - startThrottle
local startTime = tick()
while tick() - startTime < duration do
local elapsed = tick() - startTime
local t = math.clamp(elapsed / duration, 0, 1)
local eased = t * t * (3 - 2 * t) -- smoothstep easing
throttleObject.Value = startThrottle + delta * eased
task.wait()
end
throttleObject.Value = targetThrottle
end
-- Function to move a single train
function TrainController.moveTrain(train, line, maxSpeed, previousTrain)
print("Starting to run train")
local currentWaypoint = 1
local sections = LineRoute.GetRouting(line)
for i, section in pairs(sections) do
print("New section started: " .. section)
local waypoints = workspace.Waypoints:FindFirstChild(section):GetChildren()
waypoints = TrainController.sortWaypoints(waypoints)
while true do
if currentWaypoint > #waypoints then
currentWaypoint = 1
break
end
if previousTrain == nil then
if waypoints[currentWaypoint]:FindFirstChild("Approaching") then
warn("Audio: ./Now_arriving_at/"..sections[#sections].."/Station/")
end
if waypoints[currentWaypoint]:FindFirstChild("Station") then
TrainController.AdjustThrottle(train, 0, 3)
local doorSide = waypoints[currentWaypoint]:FindFirstChild("Station").Value
warn("Audio: ./This_is/"..sections[#sections].."/Doors_will_open_on_the/"..doorSide.."/")
end
end
if waypoints[currentWaypoint]:FindFirstChild("Start") then
train:SetPrimaryPartCFrame(waypoints[1].CFrame)
else
local targetWaypoint = waypoints[currentWaypoint]
local targetCFrame = targetWaypoint.CFrame
local distance = (targetCFrame.Position - train.PrimaryPart.Position).Magnitude
local startCFrame = train.PrimaryPart.CFrame
local startTime = tick()
while true do
local throttle = train.Parent.Parent:FindFirstChild("Throttle") and train.Parent.Parent.Throttle.Value or 0
local speed = throttle * maxSpeed
if speed <= 0 then
task.wait()
continue
end
local elapsed = tick() - startTime
local alpha = math.min((elapsed * speed) / distance, 1)
train:SetPrimaryPartCFrame(startCFrame:Lerp(targetCFrame, alpha))
if alpha >= 1 then
break
end
task.wait()
end
end
-- Move to the next waypoint
currentWaypoint += 1
end
end
if previousTrain == nil then
train.Parent.Parent.Throttle.Value = 0
end
end
return TrainController
Here is the file if you guys want to do some testing
train_testing_2.rbxl (124.4 KB)
Thanks for your time,
fxk3b.