I simply just want a easy way for a NPC to control a vehicle, hopefully using the VehicleSeat steering and throttle values (as thats how my driving script works) to move.
I have tried having the NPC use :MoveTo(), it doesn’t work.
The only way I can instantly think of is calculating the direction to the target point and adjusting the VehicleSeat’s throttle and steering to drive the vehicle towards that target.
This will involve using VehicleSeat’s Throttle and Steering properties, but we’ll need to add logic for navigation, steering, and continuously adjusting these values.
Get the target point that the NPC is supposed to drive towards.
Calculate the direction to the target and adjust the throttle and steering accordingly.
Move the vehicle until the NPC reaches the target.
So maybe something like:
local npc = game.Workspace:WaitForChild("NPC")
local vehicle = game.Workspace:WaitForChild("Vehicle") -- Replace with your vehicle
local vehicleSeat = vehicle:WaitForChild("VehicleSeat") -- Get the VehicleSeat inside the vehicle
local targetPosition = Vector3.new(100, 0, 100) -- Replace with the target position you want the NPC to actually drive to, if we just read the moveto values from the humanoid, theres a chance it interfears and whatever else idrk.
-- Function to move the NPC-controlled vehicle towards a target
local function driveToTarget()
local target = targetPosition
local vehiclePos = vehicle.PrimaryPart.Position
-- Continue moving until we reach the target
while (vehiclePos - target).Magnitude > 5 do -- Check if we're close to the target (5 studs tolerance)
vehiclePos = vehicle.PrimaryPart.Position
-- direction to the target / direction vector
local direction = (target - vehiclePos).unit -
-- steering angle
local steering = math.clamp(direction.X, -1, 1) -- Clamp between -1 and 1 for steering (because thats the min and max for vehicle seats
-- Set throttle to full throttle
vehicleSeat.Throttle = 1 -- Full throttle
-- Set steering based on the direction to the target
vehicleSeat.Steering = steering
-- Wait for the next frame to update
task.wait(0.1)
end
-- Stop the vehicle when close to the target
vehicleSeat.Throttle = 0 -- Stop the vehicle
vehicleSeat.Steering = 0 -- Straighten the steering
end
driveToTarget()
I noticed ur npc was already in the seat so I assume you alread y have code for that!
If i remember the default jeep has a code that only works for the player. you would have to create a new code that makes the jeep not go down when npc sits. Then manipulate the steering and throttle values
The script for controlling the vehicle would be inside the NPC, preferably part of the script used to walk to the car.
The script currently looks like this:
local PathfindingService = game:GetService("PathfindingService")
local DriverHumanoid = script.Parent.Humanoid
local DriverCar = nil
local DebugModeVal = script.Parent.DebugMode
script.Parent.HumanoidRootPart["bad to the bone guitar riff"]:Play()
while true do
local VehicleSeat = nil
for i,v in pairs(script.VehicleSearchObject.Value:GetChildren()) do
if v:FindFirstChild("NPCAccessable") and v:FindFirstChild("NPCAccessable").Value == true and v:FindFirstChildOfClass("VehicleSeat") and v:FindFirstChildOfClass("VehicleSeat").Occupant == nil then
VehicleSeat = v:FindFirstChildOfClass("VehicleSeat")
end
end
script.Parent.Head.DebugGui.TextLabel.Text = "Currently: moving to vehicle"
local startPosition = script.Parent.HumanoidRootPart.Position
local finishPosition = VehicleSeat.Position
local path = PathfindingService:CreatePath({
AgentRadius = 3,
AgentHeight = 6,
AgentCanJump = true,
AgentCanClimb = true,
WaypointSpacing = 4
})
-- Compute the path
local success, errorMessage = pcall(function()
path:ComputeAsync(startPosition, finishPosition)
end)
-- Confirm the computation was successful
if success and path.Status == Enum.PathStatus.Success then
-- For each waypoint, create a part to visualize the path
for _, waypoint in path:GetWaypoints() do
local part = Instance.new("Part")
part.Position = waypoint.Position
part.Size = Vector3.new(0.5, 0.5, 0.5)
part.Color = Color3.new(0.333333, 0.666667, 0)
part.Anchored = true
part.CanCollide = false
if DebugModeVal.Value == false then
part.Transparency = 1
end
part.Parent = workspace
DriverHumanoid:MoveTo(part.Position,part)
game.Debris:AddItem(part,5)
DriverHumanoid.MoveToFinished:Wait()
end
else
print(`Path unable to be computed, error: {errorMessage}`)
end
local partsInArea = workspace:GetPartBoundsInRadius(script.Parent.HumanoidRootPart.Position,8)
if table.find(partsInArea,VehicleSeat) and VehicleSeat.Occupant == nil then
VehicleSeat:Sit(DriverHumanoid)
--Start vehicle control
DriverCar = VehicleSeat.Parent
local DriverTarget = script.Parent.Parent.Parent.RandomTargetPos
print("NPC inside car or smth, attempting to use :MoveTo()...")
script.Parent.HumanoidRootPart["undertale - ElectricGutar_HardMode"]:Play()
repeat
script.Parent.Head.DebugGui.TextLabel.Text = "Currently: attempting to move to ".. DriverTarget.Name.. " at ".. tostring(DriverTarget.Position)
DriverHumanoid:MoveTo(DriverTarget.Position,DriverTarget)
local walkCompleted = false
local secondsPassed = 0
local walkcompletedetect = DriverHumanoid.MoveToFinished:Connect(function(reached)
walkCompleted = true
return reached
end)
repeat
task.wait(1)
secondsPassed += 1
until walkCompleted == true or secondsPassed >= 8
walkcompletedetect:Disconnect()
until DriverHumanoid.Health <= 0
print("bro really died what a looser fr")
end
task.wait(0.5)
end
I dont really know what its trying to do… It might have something to do with the model??
Heres what it does right now (the steering value inputted into the “SteerFloat” value in the VehicleSeat is printed in the output):
Current Code:
local function driveToTarget(targetPosition:Vector3,vehicleSeat:VehicleSeat)
local target = targetPosition
local vehicle = DriverCar
local vehiclePos = vehicle.PrimaryPart.Position
-- Continue moving until we reach the target
while (vehiclePos - target).Magnitude > 5 do -- Check if we're close to the target (5 studs tolerance)
vehiclePos = vehicle.PrimaryPart.Position
-- direction to the target / direction vector
local direction = (target - vehiclePos).Unit
-- steering angle
local steering = math.clamp(direction.X, -1, 1) -- Clamp between -1 and 1 for steering (because thats the min and max for vehicle seats)
-- Set throttle to full throttle
vehicleSeat.ThrottleFloat = 1 -- Full throttle
if (vehiclePos - target).Magnitude <= 20 then
vehicleSeat.ThrottleFloat = 0.5
end
print(steering)
-- Set steering based on the direction to the target
vehicleSeat.SteerFloat = steering
-- Wait for the next frame to update
task.wait(0.1)
end
-- Stop the vehicle when close to the target
vehicleSeat.Throttle = 0 -- Stop the vehicle
vehicleSeat.Steer = 0 -- Straighten the steering
end
So from what I’m understanding, it’s just overshooting?
I don’t know how your implementing the functions, but it would look something like this, right? (I added adjustments for steering, might fix it)
local PathfindingService = game:GetService("PathfindingService")
local DriverHumanoid = script.Parent.Humanoid
local DebugModeVal = script.Parent.DebugMode
-- Sound effect
script.Parent.HumanoidRootPart["bad to the bone guitar riff"]:Play()
-- DRIVING FUNCTION
local function driveToTarget(targetPosition: Vector3, vehicleSeat: VehicleSeat)
local vehicle = vehicleSeat.Parent
local target = targetPosition
while (vehicle.PrimaryPart.Position - target).Magnitude > 5 do
local vehicleCFrame = vehicle.PrimaryPart.CFrame
local vehiclePosition = vehicle.PrimaryPart.Position
local directionWorld = (target - vehiclePosition).Unit
local directionLocal = vehicleCFrame:VectorToObjectSpace(directionWorld)
-- Relative X is for turning left/right; Z is forward/backward
local steering = math.clamp(directionLocal.X, -1, 1)
local distance = (vehiclePosition - target).Magnitude
vehicleSeat.SteerFloat = steering
vehicleSeat.ThrottleFloat = distance <= 20 and 0.5 or 1
task.wait(0.1)
end
-- Stop vehicle
vehicleSeat.ThrottleFloat = 0
vehicleSeat.SteerFloat = 0
end
while true do
local VehicleSeat = nil
local DriverCar = nil
-- SEARCH FOR AVAILABLE VEHICLE
for _, v in pairs(script.VehicleSearchObject.Value:GetChildren()) do
if v:FindFirstChild("NPCAccessable") and v.NPCAccessable.Value == true then
local seat = v:FindFirstChildOfClass("VehicleSeat")
if seat and seat.Occupant == nil then
VehicleSeat = seat
break
end
end
end
if VehicleSeat then
script.Parent.Head.DebugGui.TextLabel.Text = "Currently: moving to vehicle"
local startPosition = script.Parent.HumanoidRootPart.Position
local finishPosition = VehicleSeat.Position
local path = PathfindingService:CreatePath({
AgentRadius = 3,
AgentHeight = 6,
AgentCanJump = true,
AgentCanClimb = true,
WaypointSpacing = 4
})
local success, errorMessage = pcall(function()
path:ComputeAsync(startPosition, finishPosition)
end)
if success and path.Status == Enum.PathStatus.Success then
for _, waypoint in path:GetWaypoints() do
local part = Instance.new("Part")
part.Position = waypoint.Position
part.Size = Vector3.new(0.5, 0.5, 0.5)
part.Anchored = true
part.CanCollide = false
part.BrickColor = BrickColor.Green()
if not DebugModeVal.Value then
part.Transparency = 1
end
part.Parent = workspace
game.Debris:AddItem(part, 5)
DriverHumanoid:MoveTo(waypoint.Position)
DriverHumanoid.MoveToFinished:Wait()
end
else
warn("Path error: ", errorMessage)
end
-- SIT IN VEHICLE IF CLOSE
local partsInArea = workspace:GetPartBoundsInRadius(script.Parent.HumanoidRootPart.Position, 8)
if table.find(partsInArea, VehicleSeat) and VehicleSeat.Occupant == nil then
VehicleSeat:Sit(DriverHumanoid)
DriverCar = VehicleSeat.Parent
script.Parent.HumanoidRootPart["undertale - ElectricGutar_HardMode"]:Play()
local DriverTarget = script.Parent.Parent.Parent.RandomTargetPos
script.Parent.Head.DebugGui.TextLabel.Text = "Currently: driving to " .. DriverTarget.Name
driveToTarget(DriverTarget.Position, VehicleSeat)
end
end
task.wait(0.5)
end