Help with keeping parts' positions inside of a boundary

I’m making a building system and I’m having trouble keeping the builds inside of a boundary when the build is rotated. Here’s a video of my issue:

The boundary works fine when the build isn’t rotated but when I rotate it, it acts as if the build wasn’t rotated at all in terms of keeping the build inside of the boundary. I’m not really sure how I can approach the issue.

Here’s my code for keeping the build inside of the boundary:

local function clampToBoundaries(model)
	model:SetPrimaryPartCFrame(CFrame.new(
		math.clamp(model.PrimaryPart.Position.X, bounds.Position.X - bounds.Size.X/2 + model.PrimaryPart.Size.X/2, bounds.Position.X + bounds.Size.X/2 - model.PrimaryPart.Size.X/2),
		model.PrimaryPart.Position.Y,
		math.clamp(model.PrimaryPart.Position.Z, bounds.Position.Z - bounds.Size.Z/2 + model.PrimaryPart.Size.Z/2, bounds.Position.Z + bounds.Size.Z/2 - model.PrimaryPart.Size.Z/2)
		) * CFrame.Angles(0,rot,0))
end

model being the build that is being clamped to the boundary
bounds being the part that measures the boundary
rot being the rotation of the model

I made a function for keeping a part or model inside an area earlier. It goes through every corner of every part in the model and finds the longest distance of a corner of a part from the edge. Then it calculates a new cframe based on the longest distance. So if there were corners outside the area, the corner that was furthest away from the edge will be at the edge.
Link to my post.
I have later realised that this code

for ix = 1, 2 do
	local xm =(-1)^ix
	for iy = 1, 2 do
		local ym =(-1)^iy
		for iz = 1, 2 do
			local zm =(-1)^iz

could be replaced with this

for xm = -1, 1, 2 do
	for ym = -1, 1, 2 do
		for zm = -1, 1, 2 do

Edit: @ThanksRoBama 's code is a better idea for 90 degree rotations.

Does your design only need 90 degree rotations? If so, you can figure out the “world-space size” like so:

local function clampToBoundaries(model)
    local modelSizeWorldSpace = model.CFrame:VectorToWorldSpace(model.PrimaryPart.Size)
	model:SetPrimaryPartCFrame(CFrame.new(
		math.clamp(model.PrimaryPart.Position.X, bounds.Position.X - bounds.Size.X/2 + modelSizeWorldSpace.X/2, bounds.Position.X + bounds.Size.X/2 - modelSizeWorldSpace.X/2),
		model.PrimaryPart.Position.Y,
		math.clamp(model.PrimaryPart.Position.Z, bounds.Position.Z - bounds.Size.Z/2 + modelSizeWorldSpace.Z/2, bounds.Position.Z + bounds.Size.Z/2 - modelSizeWorldSpace.Z/2)
		) * CFrame.Angles(0,rot,0))
end

That produces this:

It seems like it is rotating around a corner and that’s why it goes outside of the boundary. But I have made my own solution:

local XP
local XS
local ZP
local ZS
	
if rot ~= math.rad(90) and rot ~= math.rad(270) then
	XP = model.PrimaryPart.Position.X
	XS = model.PrimaryPart.Size.X
	ZP = model.PrimaryPart.Position.Z
	ZS = model.PrimaryPart.Size.Z
else
	XP = model.PrimaryPart.Position.Z
	XS = model.PrimaryPart.Size.Z
	ZP = model.PrimaryPart.Position.X
	ZS = model.PrimaryPart.Size.X
end
	
model:SetPrimaryPartCFrame(CFrame.new(
	math.clamp(model.PrimaryPart.Position.X, (bounds.Position.X - bounds.Size.X/2) + XS/2, bounds.Position.X + bounds.Size.X/2 - XS/2),
	model.PrimaryPart.Position.Y,
	math.clamp(model.PrimaryPart.Position.Z, (bounds.Position.Z - bounds.Size.Z/2) + ZS/2, bounds.Position.Z + bounds.Size.Z/2 - ZS/2)
) * CFrame.Angles(0,rot,0))

It basically just detects if the model is rotated and if it is switch the size axis around so the X becomes the Z and the Z becomes the X. This may not be the most efficient solution though so feel free to keep commenting.

1 Like