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)
Any help is appreciated!