Checking distance with many parts efficiently?

Currently I’m working on a door opening system which uses the distance of the player from the door. My map is relatively large and consists of many doors.

What would be the most efficient way to get a players closest distance to a door? Looping through every doors position would be an option but I’m wondering if there’s any better solution?

First do this on the client for sure. That way the server isn’t checking everyone all the time and secondly you could split the space up into regions and only check doors in or near the same region as the player.

1 Like

I’m curious of if your system could implement Proximity Prompts because if so they could be more performance friendly than probably all manual solutions, while also being more convenient.

You can also set the Style to Custom to use your own prompt UI while also being allowed to use the Proximity Prompt API.

The doors currently swing freely meaning players can walk right through them. Why I need distance is because the player has an animation while walking through the door, and I use the distance to figure out how far into the animation the player should be.

This would certainly work. Let me try to implement something like this and I’ll get back to you

maybe use a door.touched event and then loop (player.head.position - door.position).Magnitude to get the distance and break the loop when the distance is pre far

this seems pre efficient

local players = game:GetService("Players")

local doorPositions, playersClosestDoor = {}, {}

local function getDoorPositions()
	doorPositions = {}
	for _, door in ipairs(workspace:GetChildren()) do
		if door:IsA("BasePart") then --assume the door is a part instance
			if door.Name == "Door" then --assume its name is "Door"
				doorPositions[door] = door.Position
			end
		end
	end
end

local function findAllClosestDoor()
	playersClosestDoor = {}
	
	for _, player in ipairs(players:GetPlayers()) do
		local closestDoor, closestDistance = nil, math.huge
		for doorInstance, doorPosition in pairs(doorPositions) do
			local distance = player:DistanceFromCharacter(doorPosition)
			if distance < closestDistance then
				closestDoor = doorInstance
				closestDistance = distance
			end
		end
		if closestDoor then
			playersClosestDoor[player] = closestDoor
		end
	end
end

local function findOneClosestDoor(player)
	playersClosestDoor[player] = nil
	
	local closestDoor, closestDistance = nil, math.huge
	for doorInstance, doorPosition in pairs(doorPositions) do
		local distance = player:DistanceFromCharacter(doorPosition)
		if distance < closestDistance then
			closestDoor = doorInstance
			closestDistance = distance
		end
	end
	if closestDoor then
		playersClosestDoor[player] = closestDoor
	end
end

Here’s an example script I just wrote which tackles your question. Iterating over a table of door positions is very fast, minimal delay would only ever be observed if you had thousands and thousands of doors.

Sorry the the late response. I ended up doing something similar to this. Instead of zones, I loop through every door every x amount of seconds, and then doors only within a certain range will be looped through at a higher rate to find the distance. Thanks!

1 Like