How can I drive my car to Vector3 Position?

What I am trying to achieve is a car that can follow the Vector3 path that PathFindingService made. I would like to able to move the car similarly like Humanoid by doing Instance:MoveTo(<Vector3>).

I had tried BodyPosition however it doesn’t drive the car, it just moves it, and it feels very unrealistic.

I also tried doing some inefficient guessing but it didn’t work well.

Any ideas how I could make my car drive to Vector3 position. I can exclude Y-axis, since it’s not necessary for driving a car.

2 Likes

You can lerp the cars CFrame, you can find lerping online pretty easy.

Its more or less just doing:

function Lerp(StartCF,EndCF,Multiplier)
    return (EndCF - StartCF) * Multiplier
end

function MoveCar(CF)
   local Progress = 1000
    While Progress > 1000 do
       Car:SetPrimaryPartCFrame(Lerp(Car.PrimaryPart.Cframe,CF, (Progress / 1000)))
    wait(0.003)
    end
end
(Only a rough draft do not copy and paste)

You cant bro only pros can do that ur not a pro and im not a pro so ._.

Topic is very much possible depending on how you simplify it and want to make it as realistic or unrealistic as you want.

Firstly in order to achieve the task you will need a movement controller to make the car move and rotate the way you want to.

You can actually use a humanoid behave like a car by accelerating by using the:move() every renderstep.

Plus this will make the car able to deal with obstacles like a slope or moving in a curve easier rather than using a physics based solution as well humanoids can basically ignore physics for the most part and focus on following the path we want the box to go to.

yeah I mean they can climb 89 degree slopes lol. But yeah a physics solution is still possible as long as you are able to make the car move in a direction and path you want.

If this method is too unrealistic then you can do other stuff like adding raycasting to make the car slow down on slopes and such.

However if the car were to directly move straight towards the goal position as you mentioned it wouldn’t be very realistic. Consequently, the solution will be the calculate a spline curve given the set of points and have your car move along this curve. I believe this is what other games do according to my research especially within the RTS genre where the player needs to control an tank AI unit as such. There are tutorials on this on youtube so maybe check it out and see what methods they use to move the car and accelerate and brake accordingly to the path set.

@dthecoolest What about creating two rays. One ray is straight, and second ray is angled to the point it should follow. Then I could take the angle and tell the car to either go left or go right depending on the angle. Is this a good idea?


@minimic2002 That can be very useful thanks. However the car still won’t rotate its wheels, however its more realistic than BodyPosition by itself.


@iSyriux Haha. I know. However I am trying to accomplish my goal, no matter what it takes. I want to be able to that. I am still trying to do it with RayCast .

I was thinking something along the lines of this vehicle AI tutorial that is used within an RTS game within unreal engine 4.

The timestamp in the video below is the part where he deals with the steering for the car and yeah your idea with finding the amount of steer with the angle is a similar idea in order to find the steer float of the vehicle to move the vehicle to the point.

The good thing is that the coding in unreal engine 4 in this case is done visually in block coding and so it’s simpler to understand the pure logic behind the code.

An additional thing to consider is what happens if the target point is behind the car. If so then the direction of steering will also need to be different which the video talks about.

Yeah, basically it’s all if statements telling the car when to steer left and right or move forwards/backward in relationship with the target point in order to reach the goal.

Perhaps this resource will come in helpful to construct the behavior of the car in order to reach the target point since we are dealing with ai here as if we were driving the car ourselves.

1 Like

I already tried to do the angle thingy.

local straightRay = castRay(Chassis.Position, Chassis.Position + (Chassis.CFrame.LookVector * d))

eebaf6c22355f4e96ddb1bb6e35c079f-png

But it appears that it doesn’t want to make the red line go straight. Like I planned below.

e6700a442cb36f7a8b2ef5bb73372b7a-png

I believe the red line is the chassis look vector so it should just be like this. Remember to draw out the diagram on paper or in your head about the vector maths you are doing. The above line will only get you a point within the world of where the chassis is facing and not the direction.

Chassis.CFrame.LookVector * d

My math skills are at nil level. So yeah. Should I use BasePart.Orientation instead? I may sound dumb, because I am not exactly sure what are you talking about.

Do I am missing something here?

local module = {}

function module:ComputeMoveAsync(VehicleSeat, Target)
	
	local PathfindingService = game:GetService("PathfindingService")
	
	local function toVector32(vect) return Vector3.new(vect.X, 0, vect.Z) end
	local function getDistance(a, b) return (a - b).Magnitude end
	
	local function castRay(Start, End)
		local raycastParams = RaycastParams.new()
		raycastParams.FilterDescendantsInstances = {}
		raycastParams.FilterType = Enum.RaycastFilterType.Whitelist
		
		local distance = getDistance(Start, End)
		local raycastResult = workspace:Raycast(Start, (End - Start).Unit * distance, raycastParams)
		
		local raypart = Instance.new("Part")
		raypart.Name = "^"
		raypart.Anchored = true
		raypart.CanCollide = false
		raypart.Size = Vector3.new(0.2, 0.2, distance)
		raypart.CFrame = CFrame.new(End, Start) * CFrame.new(0, 0, -distance / 2)
		raypart.Parent = workspace
		
		return raypart
	end
	
	local Path = PathfindingService:CreatePath()
	Path:ComputeAsync(toVector32(VehicleSeat.Position), toVector32(Target.Position))
	
	if Path.Status == Enum.PathStatus.NoPath then return end
	
	local Waypoints = Path:GetWaypoints()
	
	for _, waypoint in pairs(Waypoints) do
		local part = Instance.new("Part")
		part.Shape = "Ball"
		part.Material = "Neon"
		part.Size = Vector3.new(0.6, 0.6, 0.6)
		part.Position = waypoint.Position
		part.Anchored = true
		part.CanCollide = false
		part.Name = "^"
		part.Parent = game.Workspace
	end
	
	local from = Waypoints[1]
	local to = Waypoints[2]
	
	local angledRay = castRay(toVector32(from.Position),toVector32(to.Position))
	angledRay.BrickColor = BrickColor.Green()
	local straightRay = castRay(toVector32(from.Position), toVector32(VehicleSeat.CFrame.LookVector * 5))
	straightRay.BrickColor = BrickColor.Red()
end

return module

image

1 Like

Nope, don’t do base part orientation that’s even more confusing as you are doing with a weird version of Euler angles known as the Tait-Bryan angles which describe yaw, pitch, roll relative to the worlds x,y,z-axis. This means the angles are relative to the worlds axis like:

--orientation is (0,0,0)
--base part will have these vectors
local up = Vector3.new(0,1,0)
local right = Vector3.new(1,0,0)
local front = Vector3.new(0,0,-1)

Don’t deal with Euler angles unless you are really math fancy.

Hmm, time to pull out my trusted ms paint skills to find the angle that you need.

I believe I mispelled green position. I meant to say green vector which is from the cars position to the target position sorry.

Then you can find the angle using the formula for between two vectors.

1 Like

I am not with masters degree so yes I won’t deal with them. I wish I could :joy:

Someone already told me but it didn’t work for some reason.

image

	local from = Waypoints[1]
	local to = Waypoints[2]
	local d = getDistance(from.Position, to.Position)
	
	local angledRay = castRay(toVector32(from.Position),toVector32(to.Position))
	angledRay.BrickColor = BrickColor.Green()
	local straightRay = castRay(toVector32(from.Position), toVector32(Vector3.new(0, 1 * d, 0)))
	straightRay.BrickColor = BrickColor.Red()

Do I just do everything upside down :thinking:, it’s not even close to being straight.

or is it because of my toVector32() function, as it removes Y-axis. But I don’t think so.

I have no idea what you are trying to do with way point 1 and way point 2. Shouldn’t it be between waypoint 1 and the position of the car? basically the waypoint you want to move towards and where the car currently is.

Anyways this should create a straightray on waypoint 1 pointing towards the direction the car is facing if that is what you were trying to find.

local endPoint = toVector32(from.Position + (Chassis.CFrame.LookVector * d))
local straightRay = castRay(toVector32(from.Position), endPoint)
straightRay.BrickColor = BrickColor.Red()

Okay thanks, it did work.
image

	local from = Waypoints[1]
	local to = Waypoints[2]
	local d = getDistance(from.Position, to.Position)
	
	local angledRay = castRay(toVector32(from.Position), toVector32(to.Position))
	angledRay.BrickColor = BrickColor.Green()
	local straightRay = castRay(toVector32(from.Position), toVector32(from.Position + (VehicleSeat.CFrame.LookVector * d)))
	straightRay.BrickColor = BrickColor.Red()
	print(getAngle(straightRay.Position, angledRay.Position))

Since angle is 3.0752872726417 (in degrees) for other points (not the one above). How we can tell where to go, like left or right? So if it’s > 0 then left, if it’s < 0 then right?

1 Like

To give it directionality we can use a cool property of the dot product which I use for my conical constraint in my inverse kinematics module shameless self-advertising sorry.

If we are given vectors a and b and we do a dot product between them we can find out directionality between these two vectors as seen in the diagram below for when the angle is 150° the dot product will become negative

Consequently, yeah we can do a bool check to find compare the direction between two vectors like so below.

local dotProduct = a:Dot(b)/(a.Magnitude * b.Magnitude)

local isOppositeDirection = false

--Detects the direction of the projection and adjust bool accordingly
if dotProduct < 0 then 
    isOppositeDirection = true
end

--if a and b same direction we will get 1 as we divide by the absolute value of itself
--if opposite we will get -1
--whoops also check for the zero condition so we don't divide
--by zero.
if dotProduct ~= 0 then
    local steerFloat = dotProduct / math.abs(dotProduct)
end

In the car example diagram I drew you can do a dot product with the car’s .RightVector and the green vector which I drew going from the position of the car towards the target waypoint.

1 Like

It keeps going in opposite direction. Unlike what I made so far:

		local angle = getAngle(straightRay.Position, angledRay.Position)
		if angle > 0 then
			print("left")
			setSteer(-1)
		elseif angle < 0 then
			print("right")
			setSteer(1)
		end

also, how can I check if the car is on the correct angle? so it doesn’t keep steering even tho its already going in correct direction

nvm my code is wrong

You gotta add a body force i think

That would make it even more complicated.

Not really. If you want the car to be anchored you can use semi implicit euler too

I don’t want my car to be anchored. I want it to go to the position that I had set, and I want car’s steer to move along, to make it seem like the car is actually driving.

Use a VectorForce