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.
- Train doesn’t want to align when spawning
- 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)
print("ready!")
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