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
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
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
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
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}
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.
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