Help with Pathfinding

Hello everyone,

I want to make NPC passengers for my airline. So far, they randomly generate as the friends of one of the players in the game.

Here’s a video of what’s going wrong:

The NPC’s are not able to pathfind correctly, as you can see, one falls over and walks into the airport seats and one doesn’t move.

Here’s my script and setup:

local npcModel = script:WaitForChild("NPCModel")

local players = game:GetService("Players")

local set = require(script.Settings)
local max = set.maximum

local folder = workspace:WaitForChild("Passengers")

local locations = script:WaitForChild("Locations")
local airportSeats = locations:WaitForChild("AirportSeats").Value

local asTable = {}
local psTable = {}

repeat task.wait() until true
repeat task.wait() until #players:GetChildren() >= 1

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

local path = PathfindingService:CreatePath({
	WaypointSpacing = 2
})

local waypoints
local nextWaypointIndex
local reachedConnection
local blockedConnection

local event = script:WaitForChild("RunCommand")

function followPath(destination, model)
	print("Pathfinding to", destination)
	
	local humanoid = model:WaitForChild("Humanoid")
	
	local success, errorMessage = pcall(function()
		path:ComputeAsync(model.PrimaryPart.Position, destination)
	end)

	if success and path.Status == Enum.PathStatus.Success then
		waypoints = path:GetWaypoints()

		blockedConnection = path.Blocked:Connect(function(blockedWaypointIndex)
			if blockedWaypointIndex >= nextWaypointIndex then
				blockedConnection:Disconnect()
				followPath(destination)
			end
		end)

		if not reachedConnection then
			reachedConnection = humanoid.MoveToFinished:Connect(function(reached)
				if reached and nextWaypointIndex < #waypoints then
					nextWaypointIndex += 1
					humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
				else
					reachedConnection:Disconnect()
					blockedConnection:Disconnect()
				end
			end)
		end

		nextWaypointIndex = 2
		humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
		
		local new = Instance.new("Part")
		new.Parent = workspace
		new.Anchored = true
		new.CanCollide = false
		new.Size = Vector3.new(0.5,0.5,0.5)
		new.Position = waypoints[nextWaypointIndex].Position
	else
		warn("Path not computed!", errorMessage)
	end
end

function addNewSeats(model)
	if not model then return end
	
	for i, v in ipairs(model:GetDescendants()) do
		if v:IsA("Seat") then
			table.insert(asTable, v)
			
			print("Seat inserted:", v.Name)
		end
	end
end

function airportSit(hum)	
	if not hum then return end
	
	task.wait(1)
	
	local rand = math.random(1, #asTable)
	
	local seat = asTable[rand]
	
	local animator = hum.Animator
	local track = animator:LoadAnimation(script:WaitForChild("Sit"))
	
	if seat:IsA("Seat") and not seat.Occupant then
		task.wait(4)
		
		if seat.Occupant then
			table.remove(asTable, rand)

			local replacement = math.random(1, #asTable)
			local rseat = asTable[replacement]
			
			if rseat.Occupant then
				hum.Parent:Destroy()
			end

			if rseat:IsA("Seat") and not rseat.Occupant then		
				rseat:Sit(hum)
			end
		end
		
		seat:Sit(hum)
		
		track:Play()
	elseif seat.Occupant then
		
		task.wait(4)
		
		table.remove(asTable, rand)
		
		local replacement = math.random(1, #asTable)
		local rseat = asTable[replacement]
		
		if rseat:IsA("Seat") and not rseat.Occupant then		
			rseat:Sit(hum)
		end
	end
end

function lookForPlane()
	workspace.DescendantAdded:Connect(function(descendant)
		if descendant.Name == set.planeModelName then
			print("Plane Model Detected!")
		end
	end)
end

function dressNPC(npc, player)
	local friends = players:GetFriendsAsync(player.UserId)
	
	local ids = table.create(200)
	local count = 1

	while true do
		for _, item in ipairs(friends:GetCurrentPage()) do
			ids[count] = item.Id
			count += 1
		end

		if friends.IsFinished then
			break
		end

		friends:AdvanceToNextPageAsync()
	end

	local randomFriendId = ids[math.random(1, count)]
	
	local Success, Result = pcall(function() return players:GetHumanoidDescriptionFromUserId(randomFriendId) end)
	
	local HumanoidDescription = npc:WaitForChild("Humanoid")
	
	if Success and Result then
		HumanoidDescription:ApplyDescription(Result)
	else
		warn(Result)
	end
	
	task.wait()
end

coroutine.wrap(addNewSeats)(airportSeats)
coroutine.wrap(lookForPlane)

for i = 1, max do
	local newModel = npcModel:Clone()
	
	newModel.Parent = folder
	
	local hum = newModel:WaitForChild("Humanoid")
	
	task.wait()
	
	coroutine.wrap(dressNPC)(newModel, players:GetPlayers()[math.random(1, #players:GetPlayers())])
	
	local PhysicsService = game:GetService("PhysicsService")
	local Players = game:GetService("Players")

	PhysicsService:RegisterCollisionGroup("NPCs")
	
	PhysicsService:CollisionGroupSetCollidable("NPCs", "NPCs", false)
	PhysicsService:CollisionGroupSetCollidable("NPCs", "Default", true)
	PhysicsService:CollisionGroupSetCollidable("Characters", "Characters", false)
	PhysicsService:CollisionGroupSetCollidable("Characters", "NPCs", false)

	local function onDescendantAdded(descendant)
		if descendant:IsA("BasePart") or descendant:IsA("MeshPart") or descendant:IsA("UnionOperation") then
			descendant.CollisionGroup = "NPCs"
		end
	end

	local function onCharacterAdded(model)
		for _, descendant in pairs(model:GetDescendants()) do
			onDescendantAdded(descendant)
		end
		model.DescendantAdded:Connect(onDescendantAdded)
	end

	onCharacterAdded(newModel)
	
	print("NPC", newModel.Name, "collision group set to NPCs")
end

for i, v in ipairs(folder:GetChildren()) do
	local hum = v:WaitForChild("Humanoid")
	
	coroutine.wrap(airportSit)(hum)
end

event.Event:Connect(function()
	for i, v in ipairs(folder:GetChildren()) do
		local hum = v:WaitForChild("Humanoid")

		hum.Jump = true
		
		for i,v in pairs(hum.Animator:GetPlayingAnimationTracks()) do
			v:Stop()
		end

		task.wait(2)

		coroutine.wrap(followPath)(workspace.PathfindToPart.Position, hum.Parent)
	end
end)

image

Any help is appreciated!