Best way to get closest player?

Hi,

Currently I have a bot that follows players around a map using PathfindingService. Periodically it will check to make sure there isn’t another player closer than the one it is currently chasing. In order to quickly do this check, the bot grabs the magnitude of its position and each player’s position and determines who to chase based on shortest distance.

In certain situations this method of checking who is closer is inaccurate as seen in image below.

As you can see Player2 (yellow path) should be closer than Player1 (green path), but by using the magnitude check, the red distance is obviously shorter, so the bot will choose to chase Player1.

Now an obvious solution would be to calculate the length of the path to each player and use this value to determine who is actually closer, but I feel this would be too costly.

Is there another way to achieve a more accurate solution without doing any costly calculations?

Thanks

There seems to be a thread regarding this already, try to see if you find anything useful!

Thanks,
The thread you linked appears to be more of a discussion on whether it is better to use DistanceFromCharacter method or calculating the magnitude between two points. Either direction for me still yields the incorrect behavior as shown in the picture above.

I am looking for a solution that would make the bot chase Player2 in this scenario, rather than Player1.

2 Likes
function ComputePathLength(waypoints)
    local distance = 0
    for i,point in ipairs(waypoints) do
        if waypoints[i+1] ~= nil then
            distance += (point.Position-waypoints[i+1].Position).Magnitude
        end
    end
    return distance
end

This was written assuming that you will pass the argument returned by the Path:GetWaypoints() function.
It will compute the full length of the path and return the true distance of the path; the only real math that is being done is a magnitude calculation and the use of the += operator.

Thanks,
I considered this, but was worried about 20+ waypoint paths, meaning 20+ sqrt calculations, multiplied by the number of characters.
I know Unity has a Vector3.sqrMagnitude method that basically calculates a squared magnitude. I might try implementing the approach you have above but using my own custom sqrMagnitude method and see if I notice any significant slowdown.

1 Like

So I went with a modified version of @overflowed answer where instead of computing the magnitude, I compute my own custom squared magnitude.

function SqrMagnitude(position1, position2)
	local sqrMag = (position2.x - position1.x) ^ 2 + (position2.y - position1.y) ^ 2 + (position2.z - position1.z) ^ 2
	return sqrMag
end

function ComputePathLength(waypoints)
	local distance = 0
	for i = 2, #waypoints, 1 do
		distance = distance + SqrMagnitude(waypoints[i - 1].Position, waypoints[i].Position) 
	end
	return distance
end

I also added a timer so that when I find a new closest player to chase, I wait a few seconds before attempting to locate another.

I have tested on device and it works without any noticeable slowdown.