So I have these models that I got from the toolbox and i’m done with all the coding and stuff for this models. I’m trying to make a train that moves so I used TweenService to tween every model. So it tweened pretty well but they are somehow separating and sometimes even too close to each other.
-
What is the issue? Include screenshots / videos if possible!
The problem is, they are separating like they are leaving the others behind. But its unrealistic for trains in real life that their carriages separate. In real life while the train is moving, the train cars are not separating unless someone pulls the pin between the other cars, that will cause one car to be left behind. So its basically the same as in the problem as mine.
Here’s pictures:
Well I tried this topic:Limit CFrame to certain radius? to look for some solutions but any of them didn’t work. Because it’s an old topic, I tried asking for some things but I don’t get any answer.
THE TWEENING CODE:
local TweenInfo = TweenInfo.new(
Time,
Enum.EasingStyle.Linear,
Enum.EasingDirection.InOut,
0,
false,
0
)
TweenService:Create(Carriage.PrimaryPart,TweenInfo,{CFrame = Node.CFrame + Vector3.new(0,Carriage.PrimaryPart.Size.Y/5,0)}):Play()
Plus I use nodes so the train will follow each node. The nodes contain position and rotation.
Here is the full code I know it’s very long:
This for the main script for the train to move
local TrainSuperClass = {}
TrainSuperClass.__index = TrainSuperClass
local Workspace = game:GetService("Workspace")
local TweenService = game:GetService("TweenService")
local RunService = game:GetService("RunService")
local ServerStorage = game:GetService("ServerStorage")
local Carriages = ServerStorage.Carriages
local RunService = game:GetService("RunService")
function TrainSuperClass.new(TrainModel,Nodes)
local Train = {}
setmetatable(Train,TrainSuperClass)
Train.Nodes = Nodes
Train.Dummy = TrainModel
Train.Node = 0
Train.LasCarriage = nil
return Train
end
function TrainSuperClass:Setup()
print("Train has started!")
self.Train = self.Dummy:Clone()
self.Train.Parent = Workspace.Train
self:Move()
end
function TrainSuperClass:GetTime(Distance)
return Distance / self.Speed
end
function TrainSuperClass:Carriages(Node)
local Carriage = Carriages:GetChildren()[math.random(1,#Carriages:GetChildren())]:Clone()
local All = Carriage:GetChildren()
for A = 1,#All do
if (All[A].Name~= self.Train.PrimaryPart and All[A]:IsA("BasePart")) then
local NewWeld = Instance.new("Weld")
NewWeld.Name = "Weld"
NewWeld.Part0,NewWeld.Part1 = All[A],Carriage.PrimaryPart
NewWeld.C0 = All[A].CFrame:inverse()
NewWeld.C1 = Carriage.PrimaryPart.CFrame:inverse()
NewWeld.Parent = Carriage.PrimaryPart
end
end
if not (self.LastCarriage) then
self.LastCarriage = self.Train
end
local Range = NumberRange.new(1,2)
Carriage:SetPrimaryPartCFrame(self.LastCarriage:GetPrimaryPartCFrame() * CFrame.new(0,0,Carriage.PrimaryPart.Size.Z+2))
self.LastCarriage = Carriage
self.LastCarriage.Name = "LastCar"
Carriage.Parent = Workspace.Train
spawn(function()
wait()
self:MoveCarriage(Node,Carriage)
end)
end
function TrainSuperClass:MoveCarriage(NodeNum,Carriage)
local Node = self.Nodes:FindFirstChild("Node"..NodeNum)
if not (Node) then
Carriage:Destroy()
return
end
local Distance = (Carriage.PrimaryPart.CFrame.p - Node.CFrame.p).Magnitude
local BetweenDistance = (Carriage.PrimaryPart.CFrame.p - self.LastCarriage.PrimaryPart.CFrame.p).Magnitude
local Time = self:GetTime(Distance)
local TweenInfo = TweenInfo.new(
Time,
Enum.EasingStyle.Linear,
Enum.EasingDirection.InOut,
0,
false,
0
)
TweenService:Create(Carriage.PrimaryPart,TweenInfo,{CFrame = Node.CFrame + Vector3.new(0,Carriage.PrimaryPart.Size.Y/5,0)}):Play()
wait(Time)
self:MoveCarriage(NodeNum + 1,Carriage)
end
function TrainSuperClass:Move()
self.Node = self.Node + 1
local Node = self.Nodes:FindFirstChild("Node"..self.Node)
if not(Node) then
self:Stop()
return
end
if self.Node == 1 then
local All = self.Train:GetChildren()
for A = 1,#All do
if (All[A].Name~= self.Train.PrimaryPart and All[A]:IsA("BasePart")) then
local NewWeld = Instance.new("Weld")
NewWeld.Name = "Weld"
NewWeld.Part0,NewWeld.Part1 = All[A],self.Train.PrimaryPart
NewWeld.C0 = All[A].CFrame:inverse()
NewWeld.C1 = self.Train.PrimaryPart.CFrame:inverse()
NewWeld.Parent = self.Train.PrimaryPart
end
end
wait()
self.Train:SetPrimaryPartCFrame(Node.CFrame + Vector3.new(0,self.Train.PrimaryPart.Size.Y/2,0))
for i = self.CarriagesCount,1,-1 do
self:Carriages(self.Node)
end
self:Move()
return
end
local Distance = (self.Train.PrimaryPart.CFrame.p - Node.CFrame.p).Magnitude
local Time = self:GetTime(Distance)
local TweenInfo = TweenInfo.new(
Time,
Enum.EasingStyle.Linear,
Enum.EasingDirection.InOut,
0,
false,
0
)
local Range = NumberRange.new(1.5,2)
TweenService:Create(self.Train.PrimaryPart,TweenInfo,{CFrame = Node.CFrame + Vector3.new(0,self.Train.PrimaryPart.Size.Y/2,0)}):Play()
wait(Time)
self:Move()
if (self.Node == 10) then
print("Node is ten yen....")
end
end
function TrainSuperClass:Stop()
self.LastCarriage = nil
self.Train:Destroy()
self.Train.Parent = nil
self.Node = 0
print("Train has finished! Starting setup...")
wait(14)
self:Setup()
end
return TrainSuperClass
The script inside the model of the train (the main train car, the very front)
local ServerScriptService = game:GetService("ServerScriptService")
local SuperClasses = ServerScriptService.SuperClasses
local TrainSuperClass = require(SuperClasses.TrainSuperClass)
local TrainClass = {}
TrainClass.__index = TrainClass
setmetatable(TrainClass,TrainSuperClass)
function TrainClass.new(...)
local self = TrainSuperClass.new(...)
setmetatable(self,TrainClass)
self.Speed = 60
self.CarriagesCount = math.random() + 5 * 2 - 3 -- Random amount of train cars
return self
end
return TrainClass
Sorry for that long line, its very a long code and its kinda comples if you asked me.
So if you have any suggestions reply below. Any of you know any ideas? Let me know in the replies. Do you know any ways of calculating the distance between each train car? Reply below