Finding the closest object to a player

local closestObject = nil
local closestDistance = nil
RunService.Heartbeat:Connect(function()
	for _, Part in pairs(game.Workspace.items:GetChildren()) do
		local distance = (Part.Handle.Position - c.HumanoidRootPart.Position).Magnitude
		if distance <= 10 then
			db = true
			
			print("Closest object is ".. closestObject.Name)
		end
	end
	db = false
end)

So I’m trying to make a script where you pick up items when you click F. But I need to find the closest item so I can show the GUI and only pickup that item. Currently I have this but it’s probably not close at all. Any tips?

3 Likes

I don’t believe you actually defined closestObject, the script most likely still thinks it’s nil

It’s pretty close. You just need to add a line to compare against the current closest object.

Not sure what “db” is.

Also it’s easier if you start with

local closestDistance = math.huge

so that your first iteration doesn’t have to nil check:

local distance = --...
if distance <= 10 and distance < closestDistance then
    closestDistance = distance
    closestObject = Part
end

Also you don’t actually have the solution until the end of your loop (before the last end))

2 Likes

Yes, but what this does is the distance is going to get lower and lower and if, for example:

I go next to object 1. closest distance is 5.
Then I go next to object 2. closest distance decreases to 3.
If i go next to object 1 again but I am more than 3 away from it, it will not detect as the closest distance is 3.

I found something that will work everywhere:

local function findClosestPart(group, position)
	local closestPart, closestPartMagnitude

	local tmpMagnitude -- to store our calculation 
	for i, v in pairs(group:GetChildren()) do
		if closestPart then -- we have a part
			tmpMagnitude = (position - v.Handle.Position).magnitude

			-- check the next part
			if tmpMagnitude < closestPartMagnitude then
				closestPart = v
				closestPartMagnitude = tmpMagnitude 
			end
		else
			-- our first part
			closestPart = v
			closestPartMagnitude = (position - v.Handle.Position).magnitude
		end
	end
	return closestPart, closestPartMagnitude
end
20 Likes

this was very helpful, thank you

2 Likes

NOTE: This script returns the distance of all the parts in group to your chosen point. I recommend adding an if statement that first checks if the distance is less than a chosen value before running the code that uses the closest part (assuming if you just need the closest part to a target)

1 Like

If your game is on a large scale with many objects, I recommend using the Octree Module

Here is a tutorial

1 Like

I guess this works but, wouldn’t it be better if you just used userinputservice and then detect how far away they are from the other objects? It would also be less impactful on resources.

If you want to show the key to pick up the item User Input Service doesn’t work. You need to have the code in a loop to constantly check whether you’re close enough to an item to display the pickup key.

Oh, I thought you were on about something else. But I’m sure you could use proximitypromptservice or something to do with proximityprompts since the prompts are customizable you can make your own custom one.

That would be way more resource beneficial.

It does make some sense to use proximity prompts. I believe they didn’t exist at the time the post was created, but you still need the code to make sure you only see the prompt on the closest object.

Yeah everything else is fine, just the loop I was confused about.

1 Like