If it’s a straight race (not like a circle race) then you could do this:
I recommend doing this on each client and not the server just to prevent unnecessary load on the server (and this will involve GUI’s anyways).
So create a blank table which will track each character in the race and their distance.
-- Something like this:
local Distances = {}
for i, char in ipairs(RaceCharacters) do
local plr = Players:GetPlayerFromCharacter(char)
local distance = (char.Position - FinishLine.Position).Magnitude -- player's distance
local plrdistance = {plr.UserId, distance} -- First index is the key, second is the distance
table.insert(Distances, distance) -- Inserting it into our distances table
end
This allows us to track each player’s distance and which player accounts for that distance.
Now every heartbeat, we just have to check for the lowest distance
RunService.Heartbeat:Connect(function()
local lowestDistances = {}
for i, distance in ipairs(Distances) do -- checking for each player's distance
table.insert(lowestDistances, i, distance[2]) -- remember, the second index holds their distance from the finish line and "i" will be used to index the player later
end
local checkLowestDist = table.unpack(lowestDistances) -- unpacking table so we check minimum value
local lowestDist = math.min(checkLowestDist)
local lowestDistIndex = table.find(lowestDistances, lowestDist) -- Finding that dist in the table
local userIdLowestDist = Distances[lowestDistIndex][1] -- remember, the first index holds the player's userId
local ClosestPlayer = Players:GetPlayerByUserId(userIdLowestDist) -- Now we have the player
end)
Great, now we have the closest player
Now this optional, but you could take it a step further by checking the second, third and so on.
RunService.Heartbeat:Connect(function()
local lowestDistances = {}
for i, distance in ipairs(Distances) do -- checking for each player's distance
table.insert(lowestDistances, i, distance[2]) -- remember, the second index holds their distance from the finish line and "i" will be used to index the player later
end
local checkLowestDist = table.unpack(lowestDistances) -- unpacking table so we check minimum value
local lowestDist = math.min(checkLowestDist)
local lowestDistIndex = table.find(lowestDistances, lowestDist) -- Finding that dist in the table
local userIdLowestDist = Distances[lowestDistIndex][1] -- remember, the first index holds the player's userId
local ClosestPlayer = Players:GetPlayerByUserId(userIdLowestDist) -- Now we have the player
---------------------------------------
lowestDistances[lowestDistIndex] = nil -- We do this instead of table.remove so that the indexes are the exact same
local secondLowestDist = table.unpack(lowestDistances)
local lowestDist = math.min(checkLowestDist)
local secLowestDistIndex = table.find(lowestDistances, lowestDist)
local secondUserIdLowestDist = Distances[lowestDistIndex][1]
local SecibdClosestPlayer = Players:GetPlayerByUserId(userIdLowestDist) -- Rinse and repeat
end)
Now you could put that in a for i, loop until you get all the player’s positions in the race.
RunService.Heartbeat:Connect(function()
local lowestDistances = {}
for i, distance in ipairs(Distances) do -- checking for each player's distance
table.insert(lowestDistances, i, distance[2]) -- remember, the second index holds their distance from the finish line and "i" will be used to index the player later
end
local checkLowestDist = table.unpack(lowestDistances) -- unpacking table so we check minimum value
local lowestDist = math.min(checkLowestDist)
local lowestDistIndex = table.find(lowestDistances, lowestDist) -- Finding that dist in the table
local userIdLowestDist = Distances[lowestDistIndex][1] -- remember, the first index holds the player's userId
local ClosestPlayer = Players:GetPlayerByUserId(userIdLowestDist) -- Now we have the player
---------------------------------------
for i = 1, #PlayersInRace do
lowestDistances[lowestDistIndex] = nil -- We do this instead of table.remove so that the indexes are the exact same
local secondLowestDist = table.unpack(lowestDistances)
local lowestDist = math.min(checkLowestDist)
local secLowestDistIndex = table.find(lowestDistances, lowestDist)
local secondUserIdLowestDist = Distances[lowestDistIndex][1]
local SecibdClosestPlayer = Players:GetPlayerByUserId(userIdLowestDist) -- Rinse and repeat
end
end)
Anyways, hope I didn’t make it too complicated.
Final code:
local Distances = {}
for i, char in ipairs(RaceCharacters) do
local plr = Players:GetPlayerFromCharacter(char)
local distance = (char.Position - FinishLine.Position).Magnitude
local plrdistance = {plr.UserId, distance}
table.insert(Distances, distance)
end
RunService.Heartbeat:Connect(function()
local lowestDistances = {}
for i, distance in ipairs(Distances) do -- checking for each player's distance
table.insert(lowestDistances, i, distance[2]) -- remember, the second index holds their distance from the finish line and "i" will be used to index the player later
end
local checkLowestDist = table.unpack(lowestDistances) -- unpacking table so we check minimum value
local lowestDist = math.min(checkLowestDist)
local lowestDistIndex = table.find(lowestDistances, lowestDist) -- Finding that dist in the table
local userIdLowestDist = Distances[lowestDistIndex][1] -- remember, the first index holds the player's userId
local ClosestPlayer = Players:GetPlayerByUserId(userIdLowestDist) -- Now we have the player
---------------------------------------
for i = 1, #PlayersInRace do
lowestDistances[lowestDistIndex] = nil -- We do this instead of table.remove so that the indexes are the exact same
local secondLowestDist = table.unpack(lowestDistances)
local lowestDist = math.min(checkLowestDist)
local secLowestDistIndex = table.find(lowestDistances, lowestDist)
local secondUserIdLowestDist = Distances[lowestDistIndex][1]
local SecibdClosestPlayer = Players:GetPlayerByUserId(userIdLowestDist) -- Rinse and repeat
end
end)