Trouble with Keeping Parts in the Boundaries with Grid System

What I am attempting to achieve

What I am currently trying to achieve is to ensure a part is completely within the grid boundaries. If it’s not in bounds, it will change the hitbox color to red.

The issue

The main issue is, I cannot find an efficient way to get it to work properly and EFFICIENTLY

Solutions I’ve Tried

The main solution I tried was to have a giant transparent part covering the entire grid (known as the region part). When the player clicks on a part to start placement, the region part decreases it’s size with the x and y axis as well as creating a region with Region3, which is the same size and position as the region part. Then, every heartbeat, the script will check if all parts of the model is inside the region. Now if the user doesn’t choose to rotate the model, it works. However, if they do, it causes issues. I’ve tried many other solutions, yet none of them seems to work.

Essentially, I just need help getting it fixed up or if there’s a better and more efficient method for such.

https://gyazo.com/60e7fd4d262298f9d5b1605212e80e0b

UPDATE: Here’s some snippits of the script.

Here, this is part of the function that is called as soon as placement initiates.

	RegionArea.Size = RegionArea.Size - Vector3.new(ObjectPlacing.Hitbox.Size.X * 2 - HitboxSizeOffset, 0, ObjectPlacing.Hitbox.Size.Z * 2 - HitboxSizeOffset)
	Region = Region3.new(RegionArea.Position - (RegionArea.Size/2), RegionArea.Position + (RegionArea.Size/2))

And this is the boundary check ran every heartbeat.

	local RegionParts = workspace:FindPartsInRegion3WithWhiteList(Region, ObjectPlacing:GetDescendants(), math.huge)
	local Parts = {}
	
	for _, v in pairs(ObjectPlacing:GetDescendants()) do
		if v:IsA("BasePart") then
			table.insert(Parts, v)
		end
	end	
	
	if #Parts == #RegionParts then
		CanPlace = true
	else
		CanPlace = false
		return BrickColor.new("Really red")
	end
1 Like

Because the part is 3-dimensional, you could check to see if all of its corners (vertices) are within the region (within all 6 planes).

You would have to calculate where the vertices are (based off the part’s sizing), and then compare its Vector3 position and setup some “if statements”…

Example:

Pretend that the boundaries are at X1 = 0 and X2 = 10, Y1 = 0, Y2 = 100, Z1 = 0, Z2 = 10 (geometric planes)

For each of the vertices:

VX, VY, VZ represents the corner’s XYZ Position

if X1 < VX < X2 and Y1 < VY < Y2 and Z1 < VZ < Z2 then it’s within the bounds (for that particular vertice)

If this is true for all the vertices, you can verify that the part is within the boundaries… You don’t need Region3 at all within this setup.

Edit*
This method would also work if the part is rotated at any orientation :slight_smile:

Edit**
When you do the comparison statements (X1 < VX < X2), flip the values of X1 and X2 before hand if X2 is smaller than X1 (and do the same for the other variables Y and Z)

2 Likes

I’m quite confused by what you mean exactly as well as applying said solution. Apologies (not really good when it comes to this type of stuff).

	local Hitbox = ObjectPlacing.Hitbox
	local VX = Hitbox.CFrame * CFrame.new(-Hitbox.Size.X/2, -Hitbox.Size.Y/2, -Hitbox.Size.Z/2)
	local VY = Hitbox.CFrame * CFrame.new(-Hitbox.Size.X/2, Hitbox.Size.Y/2, -Hitbox.Size.Z/2)
	local VZ = Hitbox.CFrame * CFrame.new(-Hitbox.Size.X/2, -Hitbox.Size.Y/2, Hitbox.Size.Z/2)
	
	local X1 = -RegionArea.Size.X/2
	local Y1 = -RegionArea.Size.Y/2
	local Z1 = -RegionArea.Size.Z/2
	local X2 = RegionArea.Size.X/2
	local Y2 = RegionArea.Size.Y/2
	local Z2 = RegionArea.Size.Z/2
	
	if (X1 < VX.p.X and X2) and (Y1 < VY.p.Y and Y2) and (Z1 < VZ.p.Z and Z2) then
		CanPlace = true 
		return BrickColor.new("Lime green")	
	else
		CanPlace = false
		return BrickColor.new("Really red")	
	end

It doesn’t cause an error or any of that, but it becomes really inaccurate (will provide a gif tomorrow when I can)

1 Like

Bird’s-eye view

Basically, make sure that each vertice is somewhere between each set of planes…

I would test the “if statements” in separate blocks so that it’s easier to debug.

local vertice_1_okay = false
local vertice_2_okay = false
local vertice_3_okay = false
local vertice_4_okay = false
local vertice_5_okay = false
local vertice_6_okay = false
local vertice_7_okay = false
local vertice_8_okay = false

–determine if vertice 1 is okay (do this same process for the other 7 vertices)

local vertice_1_cframe = hitbox.CFrame * CFrame.new(hitbox.Size.X/2, 0, hitbox.Size.Z/2)

local VX = vertice_1_cframe.p.X
local VY = vertice_1_cframe.p.Y
local VZ = vertice_1_cframe.p.Z

–comparison statements:
if all the statements return true → vertice_1_okay = true

local vertice_2_cframe = hitbox.CFrame * CFrame.new(-hitbox.Size.X/2, 0, -hitbox.Size.Z/2)

local vertice_3_cframe = hitbox.CFrame * CFrame.new(hitbox.Size.X/2, 0, -hitbox.Size.Z/2)

local vertice_4_cframe = hitbox.CFrame * CFrame.new(-hitbox.Size.X/2, 0, hitbox.Size.Z/2)

local vertice_5_cframe = hitbox.CFrame * CFrame.new(0, hitbox.Size.Y/2, hitbox.Size.Z/2)

local vertice_6_cframe = hitbox.CFrame * CFrame.new(0, hitbox.Size.Y/2, -hitbox.Size.Z/2)

local vertice_7_cframe = hitbox.CFrame * CFrame.new(-hitbox.Size.X/2, hitbox.Size.Y/2, 0)

local vertice_8_cframe = hitbox.CFrame * CFrame.new(-hitbox.Size.X/2, -hitbox.Size.Y/2, 0)

Going to try it out, thank you so much! I have a much better idea now. :slight_smile:

1 Like

Hope you get it working :slight_smile:

Yup. Just tried it out and it works like a charm. Once again, thanks!

1 Like