# How to curve trains?

Hello me and @sasial are working on trains, and we have been making a node system ( I recommend to check this link How to rotate rays? - #38 by sasial )
Now we’re currently struggling with rotating every single car separately in curves. If you have any ideas to solve this problem, then it would be much appreciated. We are currently having two main problems.

1. Train doesn’t want to align when spawning
2. The train is curving in really weird way, I’ll send you picture.

and after the curve, train is looking normally.

Here is also the train script.

``````local trainoff = Vector3.new(1,9,0)
local offpos = trainoff + Vector3.new(0,0,script.OffZ.Value)
for i,v in pairs(script.Parent.Cars:GetChildren()) do
local PrimaryPart = script.Parent.Cars["Car"..i]
PrimaryPart:SetPrimaryPartCFrame(CFrame.new(workspace.Tracks.Start.PrimaryPart.Position + offpos))
offpos = offpos + Vector3.new(0,0,script.Parent.Cars["Car"..i].Box.Size.Z)
end
--- Train Script Below
local RunService = game:GetService("RunService")

local Grinding = true

local function GetDist(p)
return (p.Node1.WorldPosition - p.Node0.WorldPosition).Magnitude
end

local function GetNewPosition(p, a)
return (p.Node1.WorldPosition - p.Node0.WorldPosition) * a + p.Node0.WorldPosition
end

local function GetNewNode(currentNode, dir)
return currentNode.Part.NextNode.Value
end

local function GrindRail(Train, RailParts, CurrentPart)

--AlignPosition.Attachment1.Position = AlignPosition.Attachment0.WorldPosition

local CurrentNode = RailParts[CurrentPart]

--alpha between Node0 and Node1
local a = 0--dist2.Unit:Dot(dist1)/dist2.Magnitude
--All variables should be found by now!

--AlignPosition.Enabled = true

local connection
local CurrentRatio = GetDist(CurrentNode.Part)

connection = RunService.Heartbeat:Connect(function(dt)
a = a + dt*script.Speed.Value/CurrentRatio
print(a)
if a > 1 then
repeat
local newPart = GetNewNode(CurrentNode, 1)
if newPart then
CurrentNode = RailParts[newPart]
local NewRatio = GetDist(newPart)
a = a - 1
a = a * NewRatio/CurrentRatio
CurrentRatio = NewRatio
else
connection:Disconnect()
break
end
until a <= 1
elseif a < 0 then
repeat
local newPart = GetNewNode(CurrentNode, -1)
if newPart then
CurrentNode = RailParts[newPart]
local NewRatio = GetDist(newPart)
a = a + 1
a = a * NewRatio/CurrentRatio
CurrentRatio = NewRatio
else
connection:Disconnect()
break
end
until a >= 0
end

if CurrentNode and Grinding then
local dir = (CurrentNode.Part.Node1.WorldPosition - CurrentNode.Part.Node0.WorldPosition).Unit
--[[Train.PrimaryPart.CFrame = Train.PrimaryPart.CFrame:Lerp(CFrame.new(
GetNewPosition(CurrentNode.Part,a) + Vector3.new(0,10,0),
GetNewPosition(CurrentNode.Part,a) + Vector3.new(0,10,0) + dir
), 0.1)--]]
for i,v in pairs(script.Parent.Cars:GetChildren()) do
local car = script.Parent.Cars["Car"..i]
--        print(getdistancetonode(currentpart,dir,i))
--    print(i)
--print(ii.." "..i)
local offpos = trainoff + Vector3.new(0,0,script.OffZ.Value)
car:SetPrimaryPartCFrame(CFrame.new(
car.PrimaryPart.Position
):Lerp(CFrame.new(
GetNewPosition(CurrentNode.Part,a) + offpos + Vector3.new(-1,0,73.41*i),
GetNewPosition(CurrentNode.Part,a) + offpos + dir + Vector3.new(-1,0,73.41*i)
), 0.1))
offpos = offpos + Vector3.new(0,0,73.41*i)
wait(0.001)
end
wait(1/script.Speed.Value)
--AlignPosition.Attachment1.Position = GetNewPosition(CurrentNode.Part,a) + Vector3.new(0,3,0)
else
--AlignPosition.Enabled = false
wait(2)
Grinding = false
end

end)
end

wait(1)
print("waiting for setup...")
wait(2.3)

local train = script.Parent

local RailParts = {}
local RailModel = workspace.Tracks

for _, part in ipairs(RailModel:GetChildren()) do

RailParts[part.PrimaryPart] = {
Part = part.PrimaryPart
}
end

GrindRail(train, RailParts, workspace.Tracks.Start.PrimaryPart)
``````

Thank you for your help, it’s much appreciated.

EDIT: Grammar

2 Likes

You could make the train face the right way with CFrame.
The part where you set the CFrame of the train could be rewritten into the Nodes CFrame * CFrame.new(offpos).
Something like that.

3 Likes

Thank you for your help, do you have any idea that will help us fix this problem?

1 Like