Region3 not working and returns an empty array constantly

I have two parts which I am using their positions for the Region3 value in a running loop within a server script. The goal is to have the one part that falls through that Region3 to light up green (BrickColor change) once it is registered and stop the script. However, that does not happen and there is an empty array always without any part being registered ever. There is a GIF to see what it looks like with the middle part being the targeted part that will turn green. There are no errors in the output and I even checked references.

The parts for Region3 will be called Part1 and Part2 while the targeted part is TargetPart. Here is the code I tried:

loop = game:GetService("RunService").Stepped:Connect(function()
	local region3 = workspace:FindPartsInRegion3WithWhiteList(, Part2.Position), {TargetPart})
	for _, v in pairs(region3) do -- debug pairs but due to an empty array, never runs its contents
		if v == TargetPart then
			print("true") -- doesn't activate
	if table.find(region3, TargetPart) then -- never happens
		TargetPart.BrickColor = BrickColor.Green()

The issue is most likely that the first point passed to is “bigger” in one of the coordinates. This is a super common issue, and you’ll find plenty of topics with the same issue just by searching for Region3. Take a look at some of those threads if you need more help fixing your issue, and please use the search feature in the future ^.^

1 Like

Thank you, I will check if this is the cause when I can. I had already searched Region3 but I did not find any post close to what you had said, neither in that searching link you gave that I already looked at before.

1 Like

Sometimes it’s hard to tell if it’s your exact issue just from the titles of the posts, especially for this kind of problem where the poster can’t put their issue into words because they don’t know what’s wrong. It seems like it should be working, but it doesn’t.

Here are some posts that cover what I believe to be your problem:

Actually none of the coordinates are bigger so this post goes unsolved. The first part’s position is, 6.896, -143.77) while the second part’s position is, 16.896, -153.77). The target part is, 12.198, -150.013). I tried to reverse the part variables which would put the larger position first but it did not do anything.

1 Like

The first part’s position is, 6.896, -143.77) while the second part’s position is, 16.896, -153.77) .

-133.35 > -143.35, and
-143.77 > -153.77

so both the X and Z coordinates of the first part’s position is greater than the second part’s. Here’s a helper function that lets you construct a Region3 between two opposite Vector3 corners of the region, without having to think about which coordinates are bigger:

function Region3BetweenCorners( corner1, corner2 )
	local corner1, corner2 =
			math.min(corner1.X, corner2.X), 
			math.min(corner1.Y, corner2.Y),
			math.min(corner1.Z, corner2.Z)
			math.max(corner1.X, corner2.X), 
			math.max(corner1.Y, corner2.Y),
			math.max(corner1.Z, corner2.Z)

	return, corner2)

I don’t see the reason for using FindPartsInRegion3WithWhiteList when u can use the normal ones (which is more efficient). Declare your region separately from the API FindParts too, not sure what u were thinking there.

Here’s what I would write:

local runService = game:GetService("RunService")

local heart = runService.Heartbeat:Connect(function()
    local region =,

    local parts = workspace:FindPartsInRegion3(region)

    for _, v in pairs(parts) do
        if v == TargetPart then
            TargetPart.BrickColor = BrickColor.Green()

Yes that is why I reversed the part variables to see if it would fix, it didn’t. Do I have to actually change their positions? I put Part1 as Part2 and Part2 as Part1.

Its a test script so I can learn Region3 so efficiency doesn’t matter here. I already tried using the normal FindPartsInRegion3, no difference.

No matter which order you pass the arguments, they will always give a Region3 that can never have any parts inside, because one of the components of whichever you passed first will be greater than the corresponding component of the one you pass second:

The first part’s position is, 6.896, -143.77) while the second part’s position is, 16.896, -153.77)

If you pass them in this order, you get v1.X > v2.X, v1.Y < v2.Y and v1.Z > v2.Z. If you flip the order, you just flip the inequalities: v1.X < v2.X, v1.Y > v2.Y and v1.Z < v2.Z. There’s no way around it, you HAVE to modify the vectors that you pass into, or make sure they’re correct in some other manner e.g. by moving the parts to different corners of the region.


Oh I didn’t notice that but now I managed to fix it. Does it matter if for example if one coordinate becomes equal? For example, v1.Y = v2.Y.

Also, does the first vector passed have to be smaller than the second vector passed or does it just have to be all the same equality?

One has to be the bottom left front corner, and the other is the top right back corner. It is very specific.
If it is something that you cant really control, try to min and max the values.

For the bottom left front, use math.min on the X and Y with math.max on the Z.
Do the opposite corner, do the opposite function for each.