Detecting when parts move out of a region

In this building game, the player can place parts on a plot which can sometimes move out of the plot, like shown in the video. My problem is, how can I detect when a part leaves the plot? Here are possible solutions I’ve already looked at or tried:

  1. TouchEnded event, however roblox physics are historically not very good so I don’t want to rely on a touch ended event for this since I’m worried it might miss parts which leave the building region

  2. Magnitude checks won’t work since this building region is not spherical

  3. Workspace:GetsPartsInPart or similar functions aren’t ideal since each plot could have thousands of parts on it, and looping through each individual part would be slow, plus I’d have to keep repeating this continuously over and over again, and it would probably cause lag

Things contributing to the issue:

  1. Looping through all the plot’s parts are difficult since there could be potentially thousands of parts on each of the 12 total slots

  2. Ideally it should detect if the corners of an object are not on the plot either, so a huge 500x1x500 part can’t be sticking partially out of the plot. And this would need to work with models as well as parts

Any help is appreciated

1 Like

Although I’m unsure if this is reliable I’ll still tell you. And it also probably does require a loop so:

Region3s

1 Like

Region3 is deprecated I think, so I’d definitely be using one of the workspace functions if I were to use something related to Region3. But still, that could be very very laggy when looping through potentially 60,000 total parts continuously (5,000 parts maximum on each of the 12 slots)

1 Like

You could use ZonePlus. The creator claims that it’s good performance wise and the community seems to like it

1 Like

I’m going to take a look into how this works and look at a bit of the code myself just to make sure it’s efficient and stuff. Although I really wonder what method it would be using to keep good performance

Anyways, if everything works properly then I’ll mark this as solution. Thank you for the suggestion

1 Like

Here is some code I have made some time ago that might help you

type RegionType = {
	CFrame : CFrame,
	Size : Size,
}

-- // Local Functions

local function IsPointInRegion(Point : Vector3, Region : RegionType)
	local RegionSize = Region.Size
	local RegionCFrame = Region.CFrame
	
	local RelativeVector = RegionCFrame:PointToObjectSpace(Point)
	
	for i, v in ipairs({"X","Y","Z"}) do 
		if math.abs(RelativeVector[v]) > RegionSize[v]/2 + THRESHOLD then return false end
	end

	return true
end

local function IsPartInRegion(PartSize : Vector3, PartCFrame : CFrame, Region : RegionType)
	local RegionSize = Region.Size 
	local RegionCFrame = Region.CFrame
	
	local RelativeCFrame = RegionCFrame:Inverse() * PartCFrame
	
	local MaxX = 0
	local MaxY = 0
	local MaxZ = 0
	
	for i, v in ipairs({Vector3.new(1,1,1),Vector3.new(-1,1,1),Vector3.new(1,1,-1),Vector3.new(-1,1,-1),Vector3.new(1,-1,1),Vector3.new(-1,-1,1),Vector3.new(1,-1,-1),Vector3.new(-1,-1,-1)}) do
		local Point = RelativeCFrame * CFrame.new(PartSize/2 * v)
		MaxX = math.max(math.abs(Point.X),MaxX)
		MaxY = math.max(math.abs(Point.Y),MaxY)
		MaxZ = math.max(math.abs(Point.Z),MaxZ)
	end
	
	local Point = Vector3.new(MaxX,MaxY,MaxZ)
	
	for i, v in ipairs({"X","Y","Z"}) do 
		if Point[v] > RegionSize[v]/2 + THRESHOLD then return false end
	end

	return true
end

If you do not need the position, you could remove the CFrame element and replace it with position, that should help with performance. With that change, you might be able to loop through a significant quantity of parts without having a massive hit to performance

2 Likes