I’m trying to create a pathfinding car that uses a VehicleSeat and the Throttle/Turn values on it to make its way to a position. I’ve hooked it up to Pathfinding, however I cannot seem to get this to work. The car just indefinitely does donuts around the first point!
local des = workspace.Part.Position
local pf = game:GetService('PathfindingService')
local path = pf:CreatePath()
path:ComputeAsync(script.Parent.Position, des)
local ways = path:GetWaypoints()
function calculateAngle(target, myPos)
local rot = math.atan2(target.Z-myPos.Z,target.X-myPos.X)
local desiredAngle = math.deg(rot)+script.Parent.Orientation.Y+90
if desiredAngle > 180 then
desiredAngle = -(360-desiredAngle)
elseif desiredAngle <-180 then
desiredAngle = 360+desiredAngle
end
return desiredAngle
end
script.Parent.Throttle = 25
for i, w in pairs(ways) do
local part = Instance.new("Part")
part.Shape = "Ball"
part.Material = "Neon"
part.Size = Vector3.new(0.6, 0.6, 0.6)
part.Position = w.Position
part.Anchored = true
part.CanCollide = false
part.Parent = game.Workspace
spawn(function()
local currentPos = script.Parent.Position
local currentTarget = w.Position
local angle = calculateAngle(currentTarget, currentPos)
while calculateAngle(currentTarget, currentPos) >= 90 do
script.Parent.Steer = 1
wait()
end
while calculateAngle(currentTarget, currentPos) <= 90 do
script.Parent.Steer = -1
wait()
end
script.Parent.Steer = 0
end)
end
You should steer to the waypoint and then wait until the car gets there before you can go to the next waypoint. At the moment, you are immediately going through your for loop without reaching your waypoints. The car is randomly steering, because you multithreaded this:
I unmulti threaded and now my code looks like this.
local des = workspace.Part.Position
local pf = game:GetService('PathfindingService')
local path = pf:CreatePath()
path:ComputeAsync(script.Parent.Position, des)
local ways = path:GetWaypoints()
function calculateAngle(target, myPos)
local rot = math.atan2(target.Z-myPos.Z,target.X-myPos.X)
local desiredAngle = math.deg(rot)+script.Parent.Orientation.Y+90
if desiredAngle > 180 then
desiredAngle = -(360-desiredAngle)
elseif desiredAngle <-180 then
desiredAngle = 360+desiredAngle
end
return desiredAngle
end
for i, w in pairs(ways) do
local part = Instance.new("Part")
part.Shape = "Ball"
part.Material = "Neon"
part.Size = Vector3.new(0.6, 0.6, 0.6)
part.Position = w.Position
part.Anchored = true
part.CanCollide = false
part.Parent = game.Workspace
script.Parent.Throttle = 25
local currentPos = script.Parent.Position
local currentTarget = w.Position
local angle = calculateAngle(currentTarget, currentPos)
while calculateAngle(currentTarget, currentPos) >= 90 do
script.Parent.Steer = 1
wait()
end
while calculateAngle(currentTarget, currentPos) <= 90 do
script.Parent.Steer = -1
wait()
end
script.Parent.Steer = 0
end
However, my car seems to jiggle back and forth from going straight to toward the waypoint, etc
local des = workspace.Part.Position
local pf = game:GetService('PathfindingService')
local path = pf:CreatePath()
path:ComputeAsync(script.Parent.Position, des)
local ways = path:GetWaypoints()
function calculateAngle(target, myPos)
local rot = math.atan2(target.Z-myPos.Z,target.X-myPos.X)
local desiredAngle = math.deg(rot)+script.Parent.Orientation.Y+90
if desiredAngle > 180 then
desiredAngle = -(360-desiredAngle)
elseif desiredAngle <-180 then
desiredAngle = 360+desiredAngle
end
return desiredAngle
end
function steer(currentTarget)
local currentPos = script.Parent.Position
local angle = calculateAngle(currentTarget, currentPos)
while calculateAngle(currentTarget, currentPos) >= 90 do
script.Parent.Steer = 1
wait()
end
while calculateAngle(currentTarget, currentPos) <= 90 do
script.Parent.Steer = -1
wait()
end
script.Parent.Steer = 0
end
for i, w in pairs(ways) do
local part = Instance.new("Part")
part.Shape = "Ball"
part.Material = "Neon"
part.Size = Vector3.new(0.6, 0.6, 0.6)
part.Position = w.Position
part.Anchored = true
part.CanCollide = false
part.Parent = game.Workspace
script.Parent.Throttle = 25
local currentTarget = w.Position
repeat
steer(currentTarget)
game:GetService('RunService').Heartbeat:Wait()
print((script.Parent.Position - currentTarget).Magnitude)
until (script.Parent.Position - currentTarget).Magnitude <= 10
end
This is what I did. It sort of works but the car reaches the waypoint it continues doing donuts around it
You do not need the while loop anymore here, since repeat keeps calling steer on each Heartbeat. Instead you can just set the Steer once in the function.
I’m trying it now. It appears to reach the first waypoint and then stop steering all together until its off the map.
local des = workspace.Part.Position
local pf = game:GetService('PathfindingService')
local path = pf:CreatePath()
path:ComputeAsync(script.Parent.Position, des)
local ways = path:GetWaypoints()
function calculateAngle(target, myPos)
local rot = math.atan2(target.Z-myPos.Z,target.X-myPos.X)
local desiredAngle = math.deg(rot)+script.Parent.Orientation.Y+90
if desiredAngle > 180 then
desiredAngle = -(360-desiredAngle)
elseif desiredAngle <-180 then
desiredAngle = 360+desiredAngle
end
return desiredAngle
end
function steer(currentTarget)
local currentPos = script.Parent.Position
local angle = calculateAngle(currentTarget, currentPos) - 90
script.Parent.Steer = math.clamp(angle, -90, 90) / 90
end
for i, w in pairs(ways) do
local part = Instance.new("Part")
part.Shape = "Ball"
part.Material = "Neon"
part.Size = Vector3.new(0.6, 0.6, 0.6)
part.Position = w.Position
part.Anchored = true
part.CanCollide = false
part.Parent = game.Workspace
script.Parent.Throttle = 25
local currentTarget = w.Position
repeat
steer(currentTarget)
game:GetService('RunService').Heartbeat:Wait()
print((script.Parent.Position - currentTarget).Magnitude)
until (script.Parent.Position - currentTarget).Magnitude <= 25
script.Parent.Steer = 0
end
I found out that the angle function did not behave correctly. This is what I have now:
function getAngle(cframe, vector)
local projectedVector = cframe:PointToObjectSpace(vector)-- * Vector3.new(1, 0, 1)
local angle = math.atan2(projectedVector.Z, projectedVector.X)
return angle
end
function steer(currentTarget)
local currentPos = script.Parent.CFrame * CFrame.Angles(0, math.pi / 2, 0)
local angle = math.deg(getAngle(currentPos, currentTarget))
script.Parent.Steer = math.sign(angle)
end
Hey. I did some testing and the car is now aggressively jiggling. It seems it is trying to constantly point itself towards the goal. How would I implement something like a margin of error for the direction of the car to the waypoint?
The problem is that it always steers completely. Steer is either -1, 0 or 1.
You should try to find a formula that can make it steer smoothly depending on the angle. It should steer less when the angle is tight and more when the angle is big.