How do I make a NPC use a VehicleSeat?

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.

What is the simplest way of going about this?

Hey,

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!

lmk if this works!

1 Like

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

Im not using that script. I made my own.

The NPC walks to the seat by itself:

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
1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.