# How can I find the the closest NPC by getting the closest path?

As you can see by the title, how can I find the the closest NPC by getting the closest path?

I tried doing this by getting the least amount of waypoints to somehow get the closest path, but it always prints Player1 no matter if I move it or not.
Code:

``````local AI = script.Parent
local Humanoid = AI:WaitForChild("Humanoid")
local HumanoidRootPart = AI:WaitForChild("HumanoidRootPart")
local pathdistances
for i, v in pairs(workspace:GetChildren()) do
if v:IsA("Model") then
if string.sub(v.Name, 1, 6) == "Player" then -- all the npcs are named player1, 2, 3, and so on
local hrp = v:WaitForChild("HumanoidRootPart")
local PathfindingService = game:GetService("PathfindingService")
local path = PathfindingService:CreatePath()
path:ComputeAsync(HumanoidRootPart.Position, hrp.Position)
pathdistances = {

}
local waypoints = path:GetWaypoints()
pathdistances[v.Name] = #waypoints -- number of waypoints

print(#waypoints)
end
end
end

local smallestValue, smallestKey  = math.huge

for key, value in pairs(pathdistances) do
if value < smallestValue then
smallestKey, smallestValue = key, value
end
end

if smallestKey then
print("The closest player is "..smallestKey) -- prints Player1...?
end
``````

image of all the NPCs and AI (ai is blue)

how can I make it prints player3 pls help thanks

Hmm, looks like you are finding the smallest number of waypoints since path distances is the #waypoints which is why you are getting player 1?

Maybe try finding the distance of each path by summing up the waypoint to waypoint vectors instead to find total path distance instead.

Edit: Yeah this image should help illustrate, the amount of waypoints generated by the path finding

player3 has the least wayponts though, why should i do it this way

Because theoretically, it should work.

If you see the path finding waypoint image on the Roblox waypoint website you can see that the points are not evenly spaced with each other and that some points are close to each other to the point of overlapping.

Assuming this is true, that means it is wrong to assume the number of waypoints equals the closest path as the distance between waypoints is not the same.

Are you sure player 3 has the least amount of way points though? If so then why are you getting player1 instead:

Edit: Also the path finding system can be wonky at times, if you have played several zombie shooter games you can notice the zombies climbing up on top of each other.

Edit: Also try looking at this, someone else has tried a similar problemâ€¦ NVM I donâ€™t think its related

Okay, I see what youâ€™re saying. I made a script:

``````local AI = script.Parent
local Humanoid = AI:WaitForChild("Humanoid")
local HumanoidRootPart = AI:WaitForChild("HumanoidRootPart")
local pathdistances
local lastposition = nil
local distance = 0
for i, v in pairs(workspace:GetChildren()) do
if v:IsA("Model") then
if string.sub(v.Name, 1, 6) == "Player" then -- all the npcs are named player1, 2, 3, and so on
local hrp = v:WaitForChild("HumanoidRootPart")
local PathfindingService = game:GetService("PathfindingService")
local path = PathfindingService:CreatePath()
path:ComputeAsync(HumanoidRootPart.Position, hrp.Position)
pathdistances = {

}
local waypoints = path:GetWaypoints()
for index, waypoint in pairs(waypoints) do
if index ~= #waypoints then
if lastposition ~= nil then
distance = distance + (lastposition - waypoint.Position).Magnitude
lastposition = waypoint.Position
else
lastposition = waypoint.Position
distance = (lastposition - Vector3(0, 0, 0)).Magnitude
end
else
lastposition = nil
pathdistances[v.Name] = distance
distance = 0
end
end
end
end
end

local smallestValue, smallestKey  = math.huge

for key, value in pairs(pathdistances) do
if value < smallestValue then
smallestKey, smallestValue = key, value
end
end

if smallestKey then
print("The closest player is "..smallestKey)
end
``````

Nervmind, fixed it by doing .new, but it still says Player1â€¦

Make sure to reset the current distance for each pathfinding path

``````            local distance = 0
for index, waypoint in pairs(waypoints) do
if index ~= #waypoints then
if lastposition ~= nil then
distance = distance + (lastposition - waypoint.Position).Magnitude
lastposition = waypoint.Position
else
lastposition = waypoint.Position
distance = (lastposition - Vector3(0, 0, 0)).Magnitude
end
else
lastposition = nil
pathdistances[v.Name] = distance
distance = 0
end
end

``````

Edit: NVM, I think you did thatâ€¦

Already did, I wonder why itâ€™s doing that.

Hmm, maybe its the sum?

try this to sum up the way point vectors to find distance

``````local currentTotalDistance = 0
for i=1, #waypoints-1,1 do

local vectorToNextWayPoint = waypoints[i+1]-waypoints[i]

local distanceToNextWayPoint = vectorToNextWayPoint.Magnitude

currentTotalDistance += distanceToNextWayPoint

end

--Then store the distance in a table like you were doing before
local storeLoL = {currentTotalDistance}
``````

also, when i remove player 1 from workspace, it says player2

Hmm, in difficult situations like these I suggest visually debugging your code since it might be the pathfinding algorithm.

Try creating a part at each waypoint of the same color and do some print debugging as well.

Howdy, the method of determining which one is closest by figuring out which one has the lowest number of waypoints should work. Add a print statement to every for loop and try to gather as much information as you can from them. Ill edit this post if I come up with a solution, I am testing your problem in my own studio at the moment.

1 Like

Hey guys! Thanks so much for helping me, but I have found the problem. I was resetting the table everytime I looped to the next NPC.

Script:

``````local AI = script.Parent
local Humanoid = AI:WaitForChild("Humanoid")
local HumanoidRootPart = AI:WaitForChild("HumanoidRootPart")
local pathdistances
local lastposition = Vector3.new(0,0,0)
local distance = 0
local pathdistances = {
}
for i, v in pairs(workspace:GetChildren()) do
if v:IsA("Model") then
if string.sub(v.Name, 1, 6) == "Player" then -- all the npcs are named player1, 2, 3, and so on
local hrp = v:WaitForChild("HumanoidRootPart")
local PathfindingService = game:GetService("PathfindingService")
local path = PathfindingService:CreatePath()
path:ComputeAsync(HumanoidRootPart.Position, hrp.Position)
local waypoints = path:GetWaypoints()
for index, waypoint in pairs(waypoints) do

if index ~= #waypoints then
distance = (waypoint.Position - lastposition).Magnitude
lastposition = waypoint.Position
else
distance = (waypoint.Position - lastposition).Magnitude
lastposition = Vector3.new(0,0,0)
pathdistances[v.Name] = distance
distance = 0
end
end
end
end
end

local smallestValue, smallestKey = math.huge -- The largest number Lua can represent, just makes the loop check code easier to write

for key, value in pairs(pathdistances) do
if value < smallestValue then
smallestKey, smallestValue = key, value
end
end

if smallestKey then
print(smallestKey)
end

``````
1 Like