How do you detect parts around another part with a certain radius?

I know that I can use .Magnitude, but, I think .Magnitude can only work by directly referencing parts. Another reason is that there are going to be so many parts and referencing each one is going to be such a pain. I cannot use partsinregion because the part is moving. Here’s a quick(yet awesome) illustration:

Is there any way of doing it? The blue is the radius, the part highlighted in blue is the part that does the detection, the parts that are highlighted in yellow are the detected parts.

2 Likes

A potential solution after a small amount of digging is to:

  1. Create a circular part that covers the size of your radius and weld it to your “blue” part.
  2. Set the CanCollide to false, and then use the GetTouchingParts method to discover what parts it is intersecting.
  3. You need to add a touch interest for the non-collidable circle to be able to trigger collisions with other parts.

See BasePart | Documentation - Roblox Creator Hub

I will continue looking for another solution if you do not like this method.

3 Likes

(post deleted by author) ᅟ ᅟ ᅟ

2 Likes
2 Likes

@overflowed @Hazania
how can I do it so, that, if I have multiple parts in a model, and I only want one of them to be detected, how would I do that?

I would suggest setting a PrimaryPart for each model, and ignore any other parts that are part of model (but not the PrimaryPart) using an if statement.

Edit: If that is not feasible due to the amount of models in your game, you could alternatively loop through all the parts found and ignore any extra parts that pertain to the same model a part was already found in.

1 Like

what if I wanted to have all of them to be touched, but if they are in the same model, it only fires once?

Muahahahaha…

The cursed knowledge presents itself to you…

( Probably don’t use this lol, just funny that it happened to come up. )

3 Likes

When using GetTouchingParts(), you cannot ignore any of the parts that are touching it. What you can do is use if statements to ignore any parts that pertain to a model that was already found by another part.

Edit: Would you like an example?

local objectsFound = {}
for i, part in pairs(partToCheck:GetTouchingParts()) do
    if part.Parent:IsA(“Model”) then
        local foundObject = false
        for i, object in pairs(objectsFound) do
            if object == part.Parent then
                foundObject = true
                break
            end
        end
        if not foundObject then
            table.insert(objectsFound, part.Parent)
        end
    else
        table.insert(objectsFound, part)
    end
end

This example would assume that all of your models do not go deeper than 1 child (if you have parts within parts within models, you will need to check for more than just one parent up to see if it is within a model, potentially by using the IsDescendentOf() method or the FindFirstAncestorWhichIsA() method.

Edit: The objectsFound table is going to be a list of your parts found, no more than one part per model. Your blue part will be one of these, you probably want to add an if statement to ignore that part as well.

1 Like

Is there any way to make it more efficient/ less resource intensive?

It is probably most efficient to just use all the parts found rather than eliminate repeating model’s parts considering this is going to be checked very frequently as the “blue part” moves.

Why is it important for you to only get one part per model, if you don’t mind me asking? This may help with me determining the best solution for this problem.

4 Likes

(post deleted by author) ᅟ ᅟ ᅟ

5 Likes

Bless you for using ipairs. I don’t think it should really be about potential nils but rather what you’re iterating over and understanding the difference between ipairs/pairs. ipairs should be used for arrays.

ipairs is designed to iterate over arrays, where the keys are numeric and incremental from 1 to the length of the table. Therefore, your iterations are occurring where your keys are known at [i+1]. It is also, compared to the old VM, significantly faster. A benchmark reading at RDC showed around 6.49 speedup.

pairs should be used in cases where you’re working with dictionaries, or otherwise where your keys are not known from the beginning and can be arbitrary. pairs calls next and gets the next element based on the last key.

Another thing: ipairs will iterate your elements in order. Order is not guaranteed nor known when it comes to pairs-based iteration. Even if you have numeric keys and you use pairs, it will not default to incremental iteration. There may be some cases where order is important!

:slightly_smiling_face:

5 Likes

I actually forgot all about ipairs! Thank you for all of that info, I was pleasantly surprised. :grin:

Ok, how do I add a touch interest? I cannot find it. Sorry, this just occurred because I forgot that I needed to set the can collide to false.

Touch Interests are created automatically by connecting a BasePart to a Touched or Touch Ended event.

https://developer.roblox.com/en-us/api-reference/class/TouchTransmitter

But how would I implement that as GetTouchingParts() ?

It’s kind of a strange situation where you don’t need to connect a .Touched event, but you will have to anyways to create a Touch Interest.

Sadly, I don’t think there is another way to get one.

I would just create a .Touched event connected to the invisible part you made and let it be; it’s a waste, but it’s not going to be hampering performance.

2 Likes

If I don’t have .Touched it still detects what is touching it, but says that it is nil