Lerp isn't working correctly

Hiya,
@Fliper05YT and I are creating a train system, and lerp isn’t working for us.
Our script is here:

Script
wait(7)
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.CFrame.p - p.Node0.CFrame.p).Magnitude
end
 
local function GetNewPosition(p, a)
    return(p.Node1.CFrame - p.Node0.CFrame) + p.Node0.CFrame
end
 
local function GetNewNode(currentNode, dir)
   return currentNode.Part.NextNode.Value
end
 
local function GetCurrentNodeCFrame(currentNode,cframe)
   
end
 
local function GrindRail(Train, RailParts, CurrentPart)
 
    --AlignPosition.Attachment1.Position = AlignPosition.Attachment0.CFrame
   
    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
        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.CFrame.p - CurrentNode.Part.Node0.CFrame.p).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
                print(i)
                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)
               	print(a)
				car:SetPrimaryPartCFrame(CFrame.new(car.PrimaryPart.Position):Lerp(
                    	CurrentNode.Part.Node1.CFrame
                    	, a))
                --car.PrimaryPart.Orientation = CurrentNode.Part.Orientation
            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)

The lerp should be moving it along the track, but it is instead moving it to 0,0,0.

Thanks,
Sasial.

PS: @bantech I saw that you helped on another topic, so if you can help that would be appreciated. (:

1 Like

GIF:
fVLUnQ98lP

UPDATE:
Fixed, now it’s just not rotating.

Updated Script
wait(7)
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.CFrame.p - p.Node0.CFrame.p).Magnitude
end
 
local function GetNewPosition(p, a)
    return(p.Node1.CFrame - p.Node0.CFrame) + p.Node0.CFrame
end
 
local function GetNewNode(currentNode, dir)
   return currentNode.Part.NextNode.Value
end
 
local function GetCurrentNodeCFrame(currentNode,cframe)
   
end
 
local function GrindRail(Train, RailParts, CurrentPart)
 
    --AlignPosition.Attachment1.Position = AlignPosition.Attachment0.CFrame
   
    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
        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.CFrame.p - CurrentNode.Part.Node0.CFrame.p).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)--]]
print(a)
				print(CurrentNode.Part.Node1.CFrame.p)
			--	print(CurrentNode.Part.Node1.WorldPosition)
				
            for i,v in pairs(script.Parent.Cars:GetChildren()) do
                --print(i)
                local car = script.Parent.Cars["Car"..i]
				print(car.PrimaryPart.Position)
        --        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(
                    	CurrentNode.Part.Node1.CFrame
                    	, a))
                --car.PrimaryPart.Orientation = CurrentNode.Part.Orientation
            end
			local sp = 1/script.Speed.Value
            wait(sp*CurrentNode.Part.Size.Z)
            --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)

1 Like

To get the direction your train should be facing, get the unit vector between its current and next location.
ex.

local look = (currentPos-nextPos).unit

Face the train towards that direction by constructing a CFrame with 2 Vector3’s as its arguments.
(doing so will create a CFrame at the position of the 1st point, rotated to face the 2nd point)
ex.

local trainCF = CFrame.new(currentPos,currentPos+look)

2 Likes

LookVector isn’t a property of Vector3s, you were probably meaning Unit.

2 Likes

Issue is I am CFraming with a CFrame, not a CFrame.new
So how would I do that.

car:SetPrimaryPartCFrame(CFrame.new(car.PrimaryPart.Position):Lerp(
                    	CurrentNode.Part.Node1.CFrame
                    	, a))

@ReturnedTrue (Post above, just CCing you in)

You’ll want to have the LookAt argument in the first CFrame, and you’ll want to be Lerping to a new CFrame with the Position of the Node so you don’t get the Node’s Rotation.

For example:

local Direction = (car.PrimaryPart.Position - CurrentNode.Part.Node1.Position).Unit
local LookAt = car.PrimaryPart.Position + Direction

car:SetPrimaryPartCFrame(
    CFrame.new(car.PrimaryPart.Position, LookAt):Lerp(
        CFrame.new(CurrentNode.Part.Node1.Position),
        a
    )
)
2 Likes

Not working.
See your PM’s.
(30 chars.)

Try using TweenService, it might help you a lot. Tween the train to each part as It will automatically adjust the rotation of the train. You can still use lerp to move the train but TweenService to rotate the train. If this doesn’t work sorry because I am not the best programmer. If it doesn’t work I would use TweenService to move the train too as you might get a smoother result.

Do you have discord?
If so, DM me @ Sasial#1865,.
I’d like to discuss this more

No, sorry. I probably should get it.