This isn’t a built in feature but you can replicate it partially or fully in Lua. It will be laggy if you do it that way so I wouldn’t do it too many times in a second.
First, I’d filter out parts behind the mouse ray. Then I’d use ClosestPointOnRay and Magnitude to work out which of those parts are close enough to be affected.
I can help with it in a few hours if you want, we can see if it’s efficient enough to work in a game.
I’m very confused by what you’re asking.
What do you mean by “one part which is closest to inside the radius”? The radius is an arbitrary line segment from the center of the sphere (I assume you meant sphere, not circle) to the surface of it. Do you mean the closest part to the the center of the sphere? If that’s the case, unless the mouse is pointing at nil
, then the closet part to the center of the sphere would be Mouse.Target itself, assuming that Mouse.Target is the center of the sphere (by your drawing and natural intuition this would make sense). This is by inherent design of Mouse.Target. The closest part to the center of the sphere would have to be Mouse.Target. If the mouse is pointing at nil
(like in your drawing), then how would you know how far to go down the z-axis to get to the desired part? A part could be at 50 studs away or 300. How could you clarify which one you want? I don’t really understand what you’re trying to do here.
The only other conclusion I can come up with is that you want the second closest part when Mouse.Target is not nil. In this case, I don’t believe this is possible (see my reply below). @serieterium’s solution does not work because it does not account for the position and size of the part. The closest position to position magnitude is not the same as the closest physical presence of a part.
Actually, now that I think about it, if you assume what I said above is true (you want the second closest part to Mouse.Target), then you could use a resizing GetPartsBoundInRadius method to achieve what you want, although this is probably not the greatest idea for performance reasons. You could have your query start out as a radius of 0, and expand until it includes a part that isn’t the Mouse.Target part. This would be your second closest part besides Mouse.Target. Though again, this is terribly inefficient.
Ill rephrase what i said in the thread, i want to return the part which is closest to
mouse.Target
right. but mouse.Target
will only return a part if my mouse is actually on the part right, but im looking to extend the search range of mouse.Target
to a circular radius instead of 1 pixel. i wish to use this for an interaction system, in a function which runs every renderstep, but people are saying theres no way to do this efficiently enough? im not sure what other alternative i could use
Yeah sure, just lmk when you can
Ok. Let me just make sure I’m on the same page with you here:
Keep in mind these drawings are from TOP to BOTTOM view.
In the drawing below, assume Part A is what the target is. You do NOT want this part, you want the closest part to the center (within the range of your radius) of the Mouse.Target point. In other words, you would want Part C (because C is the closest to Mouse.Target).
Let me know if I’m correct about what I said above.
I’m still confused about your original drawing though. Below is your drawing from a bird’s eye view.
If Mouse.Target is nil
, then the mouse ray will infinitely travel until it cannot any longer. As you can see by the drawing, if Mouse.Target is nil
, the line will not stop at your part, because it has no reason to. It does not collide with anything because nothing is in the way of it. You would have to make the radius unreasonably big for it to even come near Part A, and that would obviously not be a good idea, because it would make the query very inaccurate (and inefficient).
Disregard my drawing, the first drawing which you made is essentially what im trying to achieve. The only reason I had my part 3D was for visual purposes so people may better understand what i mean, but this had the opposite effect.
Cool.
The system I’m thinking of would work using an expanding sphere. Starting out with a sphere of radius 0, it would increase its radius until the sphere touches a part (barring Mouse.Target). Here’s how I would approach this in pseudocode.
- Ensure Mouse.Target is not nil. It can’t be nil as we just described or the system won’t work.
- Given the Mouse.Target, also obtain Mouse.Hit (the position in 3D space where the mouse hits)
- Letting x start out as 0 and increment by small amounts until x == your maximum, desired radius, create a spherical spatial query of radius x UNTIL the spatial query detects a part. Yes, you will have to create a new query for every new radius. You should also blacklist Mouse.Target from being able to be a part of this query using the query’s overlap params.
.
The part that the sphere detects first should be the part closest to Mouse.Hit.
Keep in mind that the system I present is pretty inefficient. Perhaps @JarodOfOrbiter’s solution might be slightly more efficient. However, I don’t believe you will be able to achieve what you want without it being expensive.
I think we’re doing different things. My understanding of the problem was that the mouse ray would be able to act physically larger. Imagine in your second photo that the mouse hits because the brown circle would be a brown tube extending along your Z line. That was my interpretation of the problem.
I originally thought that’s what he meant, but that would still be nebulous as he stated he wanted the closest part to the mouse point, not the line. That’s what threw me off.
local mouse = game.Players.LocalPlayer:GetMouse()
local Radius = 5 --Your radius
local Array = {} --List all your parts here which you want to check on.
function GetClosestPartInRadius()
local Centre = Mouse.Hit.p
local MagTable = {}
for i,v in Array do
if (Centre - v.Position).Magnitude >= Radius then
MagTable[i] = {v,(Centre - v.Position).Magnitude}
end
end
local ActTable = table.sort(MagTable,function(a,b)
return MagTable[a][1] > MagTable[b][1]
end
return ActTable[1]
end
-- Do whatever u wish with it
Your solution will not work for the same reasons @serieterium’s solution will not work because point to center of part distance is not the same as point to closest to point on part distance.
Given the scenario in the drawing above, your code would say that Part A is closer to the middle point because the center of Part A is closer to the point than the center of Part B. While the center distance between Part A and the middle point is smaller than that of Part B and the point, the closest point on Part A to the point is a larger magnitude than the closest point on Part B to the point. We are trying to find the part that is physically closest to the point, not the part that has the closest center position.
You could use a binary search to speed this up.
- First query the max size
- If it hit more than 1 part, then query again at halve size
- If it hit more than 1 part, then query again at 1/4. Otherwise query 3/4
- Repeat step 3 with smaller and smaller steps, stop when you hit 1 part or if the step size is below a certain amount (so it doesn’t repeat forever)
Since :GetPartBoundsInRadius()
uses bounds instead of their actual volume, you could use a module to get the area that the 2 parts overlap, then do a simple distance check with that. Except that I don’t have a module for that.
ive been thinking of a little simpler solution to my problem im just not sure how this would be performance-wise as im running it every renderstep. im also wondering what the simplest solution is to this problem, as the possible solutions other posted do exceed my level of math/scripting
I absolutely love this. You are a genius.
here im trying to raycast around the mouse.hit.p in a 3d space
now i came up w this but im not sure again if theres a better method of doing this
this would save me performance compared to the old method tho, just not sure how to get the right raycast directions and origins
Didnt look on that. Thx for telling that. But are you sure raycasting in every direction is the best way. Considering the fact that there is not gonna be a part in every direction, why not raycast from the centre to the other parts centre. Its gonna reduce alot of stuff to raycast upon.
Not on almost no length.You said you were gonna use a Radius so define that as the distance. If it comes under the range consider it else leave it
Raycasting is a better solution, but still does not work. Unless you can come up with a raycasting algorithm that works 100% of the time, I’m sticking by my solution.
Here’s an example where raycasting from point to part origin fails. The red line represents the the raycast and the blue line represents the actual distance. The larger part would be marked as farther away, by the raycasting method, even though it is not.