Align with the road

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RunService = game:GetService("RunService")

local Car = ReplicatedStorage.Car
Car:PivotTo(workspace.start.CFrame)
Car.Parent = workspace

local Controller = require(ReplicatedStorage.Common.CarController):init(Car)
local PID = require(ReplicatedStorage.Common.PID)
PID.process = Car.Engine.Position

local params = RaycastParams.new()
params.FilterDescendantsInstances = {Car, workspace.target}
params.FilterType = Enum.RaycastFilterType.Blacklist

RunService.Heartbeat:Connect(function(dt)
    local result = workspace:Raycast(Car.Engine.Position, Vector3.new(0, -5, 0), params)

    if result and result.Instance.Name == 'Road' then
        -- ??
    end

    Controller:Accelerate(10)
end)

this is the code that controls the car, i have the 2 piece of road, one on the left, one on the right. i have the road thats below the car, and i want it to align itself to the road

here is the controller functions

function Static:Accelerate(speed: number)
    self.constraints.RR.AngularVelocity = -speed
    self.constraints.RL.AngularVelocity = -speed

    self.constraints.FR.AngularVelocity = -speed
    self.constraints.FL.AngularVelocity = -speed
end

function Static:Steer(angle: number)
    self.constraints.Right.TargetAngle = angle
    self.constraints.Left.TargetAngle = angle
end

function Static:MoveTo(target: Vector3)
    local diff = (target - self.FVector.Position).Unit
    local dist = (target - self.FVector.Position).Magnitude

    local dot = diff:Dot(self.FVector.CFrame.LookVector)

    local angle = math.deg(math.acos(dot)) - 90

    angle = angle > 90 and 90 - angle or angle

    local speed = self.MAX_SPEED

    if dist < self.DECELERATION_DIST then
        speed = self.MAX_SPEED * (dist / self.DECELERATION_DIST)
    end
    
    self:Steer(angle)
    self:Accelerate(speed)
end
1 Like

To align the car with the road, you can set the car’s CFrame to be the same as the CFrame of the road. Here’s how you can do that:

  1. First, get the car’s position and orientation relative to the road. You can do this by subtracting the road’s position from the car’s position, and then subtracting the road’s orientation from the car’s orientation.
  2. Next, set the car’s CFrame to be the same as the road’s CFrame, but with the car’s position and orientation relative to the road.

Here’s the code that does this:

if result and result.Instance.Name == 'Road' then 
local carPos = Car.Position - result.Instance.Position 
local carOrientation = Car.Orientation - result.Instance.Orientation 
Car.CFrame = result.Instance.CFrame * CFrame.new(carPos, carOrientation) 
end

This code will align the car’s position and orientation with the road’s position and orientation, while keeping the car’s relative position and orientation unchanged.

2 Likes

I tried to modify your code so that it works with my controller module (i am using constraints)

RunService.Heartbeat:Connect(function(dt)
    local result = workspace:Raycast(Car.Engine.Position, Vector3.new(0, -5, 0), params)

    if result and result.Instance.Name == 'Road' then

        local carPos = Car.Engine.Position - result.Instance.Position

        local carOrientation = Car.Engine.Orientation - result.Instance.Orientation

        local cf = result.Instance.CFrame * CFrame.new(carPos, carOrientation)

        workspace.debug:PivotTo(cf)

        Controller:MoveTo(cf.Position)
    end
end)
1 Like

It’s also worth noting that the RunService.Heartbeat event is fired every frame, so this code will be executed multiple times per second. This could potentially result in a lot of CPU usage, especially if the MoveTo function is computationally expensive. You may want to consider using a different event or a timer to reduce the number of times this code is executed.

2 Likes

it seems to be some piece of answer that chatGPT would say

1 Like