How can I find multiple closest parts to a player?

How can I find multiple parts from a player’s humanoid root part?

1 Like

You can create a region3 centered around the humanoid root part and then use
Workspace:FindPartsInRegion3 to find parts in the region 3.

Or you can use the Rotated Region 3 Module if you want the region to be a sphere or any other shape(performance may vary).

Edit: also make sure to make the region3 nil once you are done with it.

1 Like

could you show me how i can do this?

Hmm, I think it’s better you experiment with it first.

try doing this

--Require the rotated region 3 module

--Get the players humanoid root part CFrame
local humanoidRootPart = InsertPathToTheHumanoid here
local sphereRadius = Vector3.new(0,1,0)
local playerSphereDetector = RotatedRegion3.Ball(humanoidRootPart.CFrame, sphereRadius)

local allParts = RotatedRegion3:FindPartsInRegion3()

print(allParts[1])

--Gotta make the region 3 nil to garbage collect it since we are not using it anymore
playerSphereDetector = nil
1 Like

is it possible i can do this without region3? and also have a variable that is the amount of parts that i want to see if they are the closest ones

Oh, if you already know which parts you want to find the distance you can do this:

okay, how can i do it with multiple parts like instead of finding the closest part, find more than just oen parts that are closer to the player

It is with multiple parts though, the code in it iterates through all the parts in the folder. Then it returns only the nearest part.

1 Like

no thats not what i mean, i ewant to find multiple parts that are closest to the player

lets say i have 5 parts in workspace and i want to find 2 of the closest parts, i want a script that will print the 2 parts names

Hello there!

You can do this by getting the HumanoidRootPart and the Part magnitude.

This is a script in ServerScriptService.

local rs = game:GetService("RunService")
game.Players.PlayerAdded:Connect(function(player)--The player that joined
	player.CharacterAdded:Connect(function(char) --The player character is loaded
		
		while rs.Stepped:Wait() do
			for i, v in pairs(workspace.Partsss:GetChildren()) do --This is a model of parts that u want to detect if the player is near it
				if v.ClassName == "Part" then
					local humrp = player.Character:WaitForChild("HumanoidRootPart")--Player humanoid root part
					if humrp then
						local pos = humrp.Position - v.Position--Getting the part and humanoidrootpart Position
						local Magnitude = pos.magnitude --Getting the Magnitude
						
						if Magnitude <= 20 then --Add any number you want
							print(Magnitude)
							v:Destroy()--Destroy the part if its near it
						end
					end
				end
			end
		end
	end)
end)

How can I find multiple nearest parts?

Yeah rotated region 3 supports this, and I believe is your best bet if you don’t know how many parts you are working with.

	RotatedRegion3:FindPartsInRegion3(Instance ignore, Integer maxParts)
		> returns array of parts in the RotatedRegion3 object
		> will return a maximum number of parts in array [maxParts] the default is 20
		> parts that either are descendants of or actually are the [ignore] instance will be ignored

However, another option you could do is to:

  1. loop through the parts you want.

  2. For each part measure the distance of each part to the player, And store it in a table

  3. Sort the table in order of distance using a sorting algorithm

  4. Select the parts you want from the table (example first 5 parts, which is in first 5 indices of the table that is obtained since the distances are sorted from lowest to highest)

That is very simple.

In the Workspace,make a folder and put the parts that you want to Detect if the player is near.

In the script line 5, Change:

for i, v in pairs(game.Workspace.Partsss:GetChildren()) do

To:

for i, v in pairs(game.Workspace.YOURFOLDERWITHPARTS:GetChildren()) do

Specify what exactly you want to do in your original post so that it’s not open to ambiguity to other users trying to help. I also want to point out that the Scripting Support Subcategory is not intended to request code to be written for you – you should’ve at least tried to search the devforum and other development-related media and wrote a script. If it doesn’t work, you can come here and people here will try to fix it


This can be done using Magnitude/Player:GetDistanceFromCharacter() and tables. Basically, you’d want to iterate over all the parts and make a new entry in the table, referencing the object and the distance from the player:

local Distances = {}

for _,v in ipairs(parts) do
    Distances[#Distances + 1] = {Object = v; Distance = Player:GetDistanceFromCharacter(v.Position)}
end

Now that the entries are in the table holding the parts and their distances from the player, you can sort the table using table.sort. How it works is by iterating all possible combinations of pairs of entries and you can pass a function as an argument that’ll be used to determine the sorting order. Table sort expects the function to return true for the first entry of the combination to come before the second entry of the combination, otherwise the second will come before the first:

table.sort(Distances, function(a, b)
    return a.Distance < b.Distance
end)

Obtaining the closest parts is simple – use the indices of 1 and 2 of the table and you can get the objects since the table has been sorted in order of parts closest to the player


Resources:

3 Likes

I decided to recreate this, but it does not work when i try it with multiple parts.

code:



local function NearestParts(PartsToFind, Player)
	local Table = {}
	for i = 1, PartsToFind do
		local NearestPart = nil
		local Lenght = nil
		for i, Part in pairs(workspace:GetChildren()) do
			if Part:IsA("Part") then
				if Part.Name ~= "Baseplate" then
					local LenghtX = Player:DistanceFromCharacter(Part.Position)
					if Lenght == nil or LenghtX < Lenght then
						Lenght = LenghtX
						for i, v in pairs(Table) do
							if v ~= Part then
								Part.Transparency = 0
								table.insert(Table, Part)
							else
								Part.Transparency = 1
							end
						end
					end
				end
			end
		end
	end
end

game:GetService("RunService").Heartbeat:Connect(function()
	for _, player in pairs(game.Players:GetPlayers()) do
		if player.Character then
			local humanoidRootPart = player.Character:FindFirstChild("HumanoidRootPart")
			if humanoidRootPart then
				wait()
				NearestParts(10, player)
			end
		end
	end
end)

The previous code that I gave, sorry since I misunderstood your question, was designed to only find the nearest part. This is because of this statement:

This if statement causes the for loop to ignore parts other than the currently closest part it has found in the for loop simply put.

I recommend following the scripting logic by @Rare_tendo which provides the resources needed for you to understand the code and not just copy-paste the previous threads answer that doesn’t exactly fit your problem. Sorry for being harsh I know it’s very tempting to want to instantly and quickly find the solution to the problems you are having troubled with, I do it too.

The logic for sorting is as summarized as follows.

  1. loop through the parts you want.

  2. For each part measure the distance of each part to the player, And store it in a table along with the table of parts.

  3. Sort both tables (part table, and distance table) in order of distance using a sorting algorithm

  4. Select the parts you want from the part table since it is now organized from closest distance to furthest distance from i=1 to i = 100…

many of the posts ive seen are iterating through the parts. This will create lag for the majority of places.

You can create a expanding bubble around the player and get the touching parts. Its the least hassle and wont lag your game out.

Yeah that is true that’s why I suggested region 3 initially but I believe OP is a newbie scripter who wants to find an easier solution/alternate solution so we started discussing for loops.

The code that i gave you works for multiple parts.

It is really simple to use.
Make a folder inside workspace and name it what you want,Insert the parts that you want to detect.
Screenshot:
image

The code that i gave you,In line 5 Change:

for i, v in pairs(game.Workspace.Partsss:GetChildren()) do

To the location of your folder that has the parts inside it.

You can test it if you want to see if it works, It works for me.

Code:

local rs = game:GetService("RunService")
game.Players.PlayerAdded:Connect(function(player)--The player that joined
	player.CharacterAdded:Connect(function(char) --The player character is loaded
		
		while rs.Stepped:Wait() do
			for i, v in pairs(workspace.Partsss:GetChildren()) do --This is a model of parts that u want to detect if the player is near it. NOTE:Change the location to your folder that has parts inside it!!
				if v.ClassName == "Part" then
					local humrp = player.Character:WaitForChild("HumanoidRootPart")--Player humanoid root part
					if humrp then
						local pos = humrp.Position - v.Position--Getting the part and humanoidrootpart Position
						local Magnitude = pos.magnitude --Getting the Magnitude
						
						if Magnitude <= 20 then --Add any number you want
							print(Magnitude)
							v:Destroy()--Destroy the part if its near it
						end
					end
				end
			end
		end
	end)
end)

Can I make it so it prints more than one of the closest part? Like for example, I have 50 parts in the workspace, and I want to print multiple of the closest parts that I can change the amount of the closest parts with a variable.