Train throttle slow down not working

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 :slight_smile:
train_testing_2.rbxl (124.4 KB)

Thanks for your time,
fxk3b.

Could you clarify what kind of train system you’re trying to make? Is it a node-based system or like the one in Dead Rails?
Is the train self-driving, or does someone have to control it?
Lastly, can multiple people stand on it at the same time? If so, you shouldn’t use a train that moves with linear interpolation in the first place.

I’m trying to make a self driving train with a node based system. I believe I want multiple players to stand on the train, so how should I move the trains?

One quick question — are you making a train track system that goes from node to node (with or without an end, either randomly generated or pre-made), or is it a looped track? Also, when does the train stop ( at the last node, at a specfic waypoint, or stop anytime you would like to, …) ?

If it is not a looped track then here you go! :smiley:
train_testing_remake.rbxl (85.4 KB)
Explanation in the README script on ServerScriptService.

Yeah that’s what I wanted. Thanks so much!