I want to determine if a part is in the workspace as opposed to ServerStorage (or something else), which sounds simple enough, but the problem is that I won’t necessarily know where the part is parented. The part can be directly in the workspace, or in a folder in the workspace, or in a folder in ServerStorage, or really anywhere inbetween, so I want to know if there’s a way to find if one of it’s parents is the workspace.
I had a couple ideas on how to do this. First I looped through the workspace’s descendants to try and find the part, but I imagine that would be really expensive with a lot of objects in the workspace.
local function findPartInWorkspace(part)
for _, pt in pairs(workspace:GetDescendants()) do
if pt == part then
return true
end
end
return false
end
I also tried to loop through the parents of the parts, gradually going up in the hierarchy until the workspace is found, which would be much more efficient.
local function findPartInWorkspace(part)
while part.Parent do
if part.Parent == workspace then
return true
end
part = part.Parent
end
return false
end
Now, both of these work as intended, but I’m wondering if there’s a better way to do this. I couldn’t find anything other than workspace:FindFirstChild("Part"), which again won’t work for my purposes.
I heard somewhere in the developer hub that there is a second argument you can add to the FindFirstChild function that determines if it is recursive. If you set it to true i.e workspace:FindFirstChild("Part", true), it will loop through workspace, then the child, then the other, etc. similar to workspace:GetDesendents() and looping thorugh each one.
I see that your question is solved but I want to suggest that you step back and look at exactly why this is required. This seems like a pretty odd thing to have to do. What exactly is this for?
I’m creating a stage based game, and for performance only the current stage is loaded into the workspace. Part of what I need to happen is recognizing when a part touches another part. .Touched events weren’t reliable enough so I had to resort to constantly checking a Region3.
That region3 check is of course in a while true do loop, but that would mean it would run even while the stage is unloaded (code handled in a module). I needed the check for if the part is still in the workspace so the loop isn’t constantly running in the background when it’s not required.
If there’s a better way to do this, I’m open to suggestions, but I think my solution is pretty effective. For extra efficiency, I’m going to connect the part:IsDescendantOf(workspace) to a workspace.ChildAdded function, so I’m not constantly checking for the part as well.
Have you considered just storing which stage is active? Not that it would be significantly more efficient, just that it’s a clearer approach imo. And for the Region3 part, that’s a pretty bad way of doing it since (I assume) you’re only trying to recognize a limited number of parts. Given that it would be more efficient to loop through those parts and do the region checks yourself.
I hadn’t really thought of checking regions like that.
Now, my region is created like this, so I’ve defined the two reference points.
local min = Vector3.new(Wall.Position.X - Wall.Size.X/2, Wall.Position.Y - Wall.Size.Y/2, Wall.Position.Z - Wall.Size.Z/2)
local max = Vector3.new(Wall.Position.X + Wall.Size.X/2, Wall.Position.Y + Wall.Size.Y/2, Wall.Position.Z + Wall.Size.Z/2)
local region = Region3.new(min, max)
For a custom check, would I loop through the part(s) I’m looking for, and check if the part’s position fits inside of the XYZ region?
While this would in theory be more efficient, region3 checks will return a part that is only slightly inside of that region. For this custom check, I would need the part’s center point (where position is measured) to be inside of that region, so there’s a big margin of error there, unless I generously expand that region, to which it might just become inaccurate.
Yea, for a custom check you’d just make sure it’s >min and <max. As for the inaccuracies, that why Region3 is so inefficient. As long as you’re not using some pretty crazy unions you could take the part’s size into account, varying the range by that much. But it would probably be easier and more accurate to use Region3’s. I believe R3s have a whitelist so you might be able to add all parts that have the potential to interact with to R3 to that whitelist.
This will do pretty much what you said, with the added reliability of checking regions. I can simple create a whitelist of objects that the region will only check for, instead of looking at every single part inside of that region.