Hey! I’m having some pathfinding issues. I currently have NPC classes on the client that handle their own pathfinding. However, it appears that the paths get interrupted and mixed up?
I’m not sure if this is a caveat with pathfinding behavior I’m unaware of, or if it’s just a code issue. One thing to note, this is done in response to remote events but I’ve checked and remote events are not being handled by all NPCs at once, so it’s not a networking issue.
It appears they all go to where the first NPC is going. When the first NPC teleports to the second floor, the NPCs on the bottom go to the same place the top NPC is going with different y values.
Client NPC class (relevant functions only)
function NPCSuperClient.new(serviceBag, id, appearance)
local self = setmetatable(BaseObject.new(game.ReplicatedStorage.NPC:Clone()), NPCSuperClient)
self._serviceBag = serviceBag
self.id = id
self.appearance = appearance
self.humanoid = self._obj.Humanoid
self.character = self._obj
self._interactionService = serviceBag:GetService(InteractionServiceClient)
PromiseGetRemoteEvent("NPC_Action"):Then(function(event)
self._npcAction = event
end)
PromiseGetRemoteEvent("NPCMoveToFinished"):Then(function(event)
self._npcMoveToFinished = event
end)
PromiseGetRemoteEvent("NPCInteracted"):Then(function(event)
self._npcInteracted = event
end)
self:Enable()
return self
end
function NPCSuperClient:Enable()
self.character.UpperTorso.CanCollide = false
self._npcAction.OnClientEvent:Connect(function(action, id, ...)
if self.id ~= id then return end
if self[action] then
self[action](self, ...)
end
end)
end
function NPCSuperClient:MoveTo(position)
--@TODO; fire move to finished when done
self._currentPath = PathfindingService:CreatePath({
AgentRadius = 3,
AgentHeight = 6,
AgentCanJump = false,
})
local success, errorMessage = pcall(function()
self._currentPath:ComputeAsync(self.character.PrimaryPart.Position, position)
end)
if success and self._currentPath.Status == Enum.PathStatus.Success then
-- Get the path waypoints
local waypoints = self._currentPath:GetWaypoints()
local blockedConnection
-- Detect if path becomes blocked
blockedConnection = self._currentPath.Blocked:Connect(function(blockedWaypointIndex)
-- Check if the obstacle is further down the path
if blockedWaypointIndex >= nextWaypointIndex then
-- Stop detecting path blockage until path is re-computed
blockedConnection:Disconnect()
-- Call function to re-compute new path
self:MoveTo(position)
end
end)
-- Detect when movement to next waypoint is complete
local reachedConnection
if not reachedConnection then
reachedConnection = self.humanoid.MoveToFinished:Connect(function(reached)
if reached and nextWaypointIndex < #waypoints then
-- Increase waypoint index and move to next waypoint
nextWaypointIndex += 1
self.humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
else
reachedConnection:Disconnect()
blockedConnection:Disconnect()
-- Pathfinding is complete!
self._npcMoveToFinished:FireServer(self.id, position)
end
end)
end
-- Initially move to second waypoint (first waypoint is path start; skip it)
nextWaypointIndex = 2
self.humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
else
warn("Path not computed!", errorMessage)
end
end
Obscure behavior:

Let me know if you need to see more code or have any questions!