Hello dev’s,
I’m currently trying to make a train system for my game, however my train sometimes flings away for no reason (its y position changes to inf) like in this video:
I have already tried some fixes but none of them worked.
here is my script (its a server script):
local runs = game["Run Service"]
local train = script.Parent
local plr = game.Players:FindFirstChild(string.split(train.Name, "'")[1])
local FAST_SPEED = 200
local SLOW_SPEED = 50
local world = workspace:FindFirstChild("World1")
if not world then return end
local rails = world:FindFirstChild("Rails")
if not rails then return end
local trainSpeed = 0
local maxTrainSpeed = 0
local visual = train.PrimaryPart:Clone()
visual:ClearAllChildren()
visual.Parent = workspace
visual.Name = "Visual"
visual.Color = Color3.fromRGB(255, 0, 0)
local railPointFolder = Instance.new("Folder", rails)
railPointFolder.Name = plr.Name.."'s RailPoints"
function CreatePoint(part)
local point = Instance.new("Part")
point.Anchored = true
point.CanCollide = false
point.CanTouch = false
point.Name = "RailPoint"
point.Parent = railPointFolder
point.CFrame = part.CFrame * CFrame.new(0, 0, part.Size.Z/2)
point.Size = Vector3.new(1, 1, 1)
point.Transparency = 0.2
point.CastShadow = false
return point
end
for i, v in rails:GetChildren() do
if v:IsA("BasePart") then
CreatePoint(v)
end
end
local params = RaycastParams.new()
params.FilterType = Enum.RaycastFilterType.Include
local dist = 1000
local curPoint
local nextPoint
runs.Heartbeat:Connect(function(dt)
local points = {}
for _, v in railPointFolder:GetChildren() do
if v ~= curPoint then
table.insert(points, v)
end
end
params.FilterDescendantsInstances = points
local dir = train.PrimaryPart.CFrame:VectorToWorldSpace(Vector3.new(0, 0, -1))
local result = workspace:Shapecast(train.PrimaryPart, dir*dist, params)
visual.CFrame = result
and train.PrimaryPart.CFrame * CFrame.new(0, 0, -result.Distance)
or train.PrimaryPart.CFrame + (dir*dist)
if not result then return end
local railPoints = railPointFolder:GetChildren()
local railPoint = railPoints[table.find(railPoints, result.Instance, 1)]
if not curPoint then
curPoint = CreatePoint(train.PrimaryPart)
end
if not nextPoint then
nextPoint = railPoint
end
local distTraveledOnSection = (curPoint.Position - train.PrimaryPart.Position).Magnitude
local sectionLength = (curPoint.Position - nextPoint.Position).Magnitude
local newAlpha = (distTraveledOnSection + trainSpeed * dt) / sectionLength
train.PrimaryPart.CFrame = curPoint.CFrame:Lerp(nextPoint.CFrame, newAlpha)
if newAlpha >= 1 then
curPoint = nextPoint
nextPoint = railPoint
end
print(trainSpeed, newAlpha)
end)
while task.wait(0.05) do
local trainGear = train:GetAttribute("Speed")
if trainGear == "Fast" then
maxTrainSpeed = FAST_SPEED
elseif trainGear == "Slow" then
maxTrainSpeed = SLOW_SPEED
elseif trainGear == "Stop" then
maxTrainSpeed = 0
end
if trainSpeed < maxTrainSpeed then
trainSpeed += 1
elseif trainSpeed > maxTrainSpeed then
trainSpeed -= 1
end
if trainSpeed < 0 then
trainSpeed = 0
end
end
If this is the same print statement from the video, then it looks like newAlpha is hitting inf.
local sectionLength = (curPoint.Position - nextPoint.Position).Magnitude
local newAlpha = (distTraveledOnSection + trainSpeed * dt) / sectionLength
That’s only going to happen if sectionLength is 0 or extremely close to zero which would happen when curPoint and nextPoint are at the same position or very close to each other.
I would double check the sectionLength calculations to ensure you’re not getting zero at any point. At the very least, you can add a check to make sure sectionLength isn’t 0 and if it is, clamp newAlpha to some max value.
Hey there! If you’re struggling to implement @Uhsleep91’s solution, you can simply try this code (created off of what he said).
local runs = game["Run Service"]
local train = script.Parent
local plr = game.Players:FindFirstChild(string.split(train.Name, "'")[1])
local FAST_SPEED = 200
local SLOW_SPEED = 50
local world = workspace:FindFirstChild("World1")
if not world then return end
local rails = world:FindFirstChild("Rails")
if not rails then return end
local trainSpeed = 0
local maxTrainSpeed = 0
local visual = train.PrimaryPart:Clone()
visual:ClearAllChildren()
visual.Parent = workspace
visual.Name = "Visual"
visual.Color = Color3.fromRGB(255, 0, 0)
local railPointFolder = Instance.new("Folder", rails)
railPointFolder.Name = plr.Name.."'s RailPoints"
function CreatePoint(part)
local point = Instance.new("Part")
point.Anchored = true
point.CanCollide = false
point.CanTouch = false
point.Name = "RailPoint"
point.Parent = railPointFolder
point.CFrame = part.CFrame * CFrame.new(0, 0, part.Size.Z/2)
point.Size = Vector3.new(1, 1, 1)
point.Transparency = 0.2
point.CastShadow = false
return point
end
for i, v in rails:GetChildren() do
if v:IsA("BasePart") then
CreatePoint(v)
end
end
local params = RaycastParams.new()
params.FilterType = Enum.RaycastFilterType.Include
local dist = 1000
local curPoint
local nextPoint
runs.Heartbeat:Connect(function(dt)
local points = {}
for _, v in railPointFolder:GetChildren() do
if v ~= curPoint then
table.insert(points, v)
end
end
params.FilterDescendantsInstances = points
local dir = train.PrimaryPart.CFrame:VectorToWorldSpace(Vector3.new(0, 0, -1))
local result = workspace:Shapecast(train.PrimaryPart, dir*dist, params)
visual.CFrame = result
and train.PrimaryPart.CFrame * CFrame.new(0, 0, -result.Distance)
or train.PrimaryPart.CFrame + (dir*dist)
if not result then return end
local railPoints = railPointFolder:GetChildren()
local railPoint = railPoints[table.find(railPoints, result.Instance, 1)]
if not curPoint then
curPoint = CreatePoint(train.PrimaryPart)
end
if not nextPoint then
nextPoint = railPoint
end
local distTraveledOnSection = (curPoint.Position - train.PrimaryPart.Position).Magnitude
local sectionLength = (curPoint.Position - nextPoint.Position).Magnitude
local newAlpha = math.clamp((distTraveledOnSection + trainSpeed * dt) / sectionLength, 0, 1)
train.PrimaryPart.CFrame = curPoint.CFrame:Lerp(nextPoint.CFrame, newAlpha)
if newAlpha >= 1 then
curPoint = nextPoint
nextPoint = railPoint
end
print(trainSpeed, newAlpha)
end)
while task.wait(0.05) do
local trainGear = train:GetAttribute("Speed")
if trainGear == "Fast" then
maxTrainSpeed = FAST_SPEED
elseif trainGear == "Slow" then
maxTrainSpeed = SLOW_SPEED
elseif trainGear == "Stop" then
maxTrainSpeed = 0
end
if trainSpeed < maxTrainSpeed then
trainSpeed += 1
elseif trainSpeed > maxTrainSpeed then
trainSpeed -= 1
end
if trainSpeed < 0 then
trainSpeed = 0
end
end