FindPartsInRegion3 no longer working correctly?

Hi, I’m returning to a project I was working on a few months ago and I noticed a certain piece of functionality was no longer working correctly: FindPartsInRegion3().

Let’s take a look at this example environment. I’ve got one part at position (0,0,0).

I run the code to check for any parts occupying that point.
ExhibitB

It doesn’t recognize it is there!
This was something that was working just fine when I working on this project a couple months back so I’m wondering what changed to break this. Could it be something in the place settings that’s configured incorrectly? Was a sitewide update pushed out prematurely and this got by? I’m left scratching my head at what could be wrong.

The region your using (Vector3.new(0, 0, 0), Vector3.new(0, 0, 0)) has no volume since min and max are the same. Try (Vector3.new(-1, -1, -1), Vector3.new(1, 1, 1))

2 Likes

Yup, this is the solution! It seems at some point they patched out the ability to use the same point in both arguments to get objects overlapping that specific point.

1 Like

I think that (Vector3.new(0.5, 0.5, 0.5), Vector3.new(0.5, 0.5, 0.5)) would also work. Region3s aren’t precise (they snap to a voxel grid) .

a51d1ed41507b7736b4ae7e75a681104a763485b

Min probably gets round down to the nearest grid point while max gets round up to the nearest grid point. If both points happen to fall exactly on the grid, then neither point gets rounded.

But yeah, to avoid pesky edge cases, min and max shouldn’t be the same.

EDIT: Behold, (Vector3.new(0.5, 0.5, 0.5), Vector3.new(0.5, 0.5, 0.5)) does work:

image

NOTE: This also means that you can’t rely on just FindPartsInRegion3 to check if a point on the map is occupied! You can use this in your broadphase (if FindPartsInRegion3 returns nothing you can be sure that there’s nothing on that point, otherwise you’ll need to do more stuff to be sure.) If everything in your map is convex, then you can raycast from the point you want to check to the center of the part with only the part in its whitelist. If there’s a hit, it must be outside part, otherwise it’s inside the part.

EDIT2:

Here’s a function that checks if a point in the world is occupied by something. Like I said, non-convex meshes will throw this off. I hope your map doesn’t have donuts.

local function isPointInMapOccupied(p)
	-- Fudge the region by a bit to avoid the edgecase you saw in OP.
	local region = Region3.new(p, p+Vector3.new(1, 1, 1))
	local possible = workspace:FindPartsInRegion3(region, 10000)
	-- Broadphase: The region is bigger than the point and the region is empty. 
	-- Therefore, there must be nothing in this point.
	if #possible == 0 then return false end
	-- Test each part in the region via raycast.
	for _, part in next, possible do
		-- Raycast to the center of the part.
		local ray = Ray.new(p, part.Position-p)
		-- If we don't hit the part, then the point must be inside of the part.
		if next(workspace:FindPartOnRayWithWhitelist(ray, {part})) == nil then
			return true
		end
	end
	
	return false
end
4 Likes