Checking if part is within a base part

function round(number, to)
    to = to or 1
    return math.floor(number/to + 0.5) * to
end

function roundVector(vector, unit)
    return Vector3.new(round(vector.X, unit), 7--[[vector.Y]], round(vector.Z, unit))
end

 local renderStepped = runService.RenderStepped:Connect(function()
    if not startedPlacingWall then
    	local mouseP = mouse.Hit.p
    	pole1.CFrame = CFrame.new(roundVector(mouseP + Vector3.new(0, pole1.Size.X/2, 0), gridSize))*CFrame.Angles(0, 0, math.rad(90))
    else
   		renderStepped:Disconnect()
    end
end)

I’m trying to prevent this part from going outside of the players base plate. Atm they can move there mouse anywhere and the part will follow. I’m using the roundVector function to lock it to a 4 stud grid too, not sure if that could be helpful for incorporating that? The base plate is 160x160, but I would like to be able to change that in the future, so if the function could include the base plates size and not default size of 160x160.

You could use math.clamp to limit the X and Z values. Here’s the wiki article: https://developer.roblox.com/articles/Lua-Libraries/math#math-clamp

Here’s an example:
math.clamp(999, -160, 160) returns 160, since it’s outside of the borders. math.clamp(15, -160, 160) returns 15, since it’s bigger than -160 and smaller than 160.

1 Like
function isInBound(boundPosition, boundX, boundZ, point)
    local left = boundPosition.X
    local top = boundPosition.Z
    local right = boundPosition.X + boundX
    local bottom = boundPosition.Z + boundZ
    
    if point.X < left or right < point.X then
        return false
    end
    if point.Z < top or bottom < point.Z then
        return false
    end
    return true
end

I’m not extremely confident, but I believe this function should work.
boundPosition is the corner of the base, a vector3 value.
boundX is how far the base extends in the X direction
boundY is how far the base extends in the Z direction
point is the point you want to check is in the bounds of the base.

Sorry if this isn’t helpful, it’s my first post :grimacing:

3 Likes

How would I incorporate it though?

print(roundVector(mouseP + Vector3.new(0, pole1.Size.X/2, 0), gridSize, playersPlot.Base.Position.Y + (pole1.Size.X/2) + 0.5))

returns the parts position, but it isn’t relative to the base part, just to the world in general. So setting a math.clamp would stop it from 160 in the world, but not 160 of the base plate

I tried, set the point to mouse.Hit.p but always printed false, no matter where I moved the mouse.

Set boundPosition to be - base.Size
boundX = base.Size.X
boundZ = base.Size.Z

Use some math to calculate the world coordinate bounds of the baseplate.

LowerBoundX = Baseplate.Position.X - (Baseplate.Size.X / 2)
UpperBoundX = Baseplate.Position.X + (Baseplate.Size.X / 2)

Do the same with the Z coordinates.

The position of the baseplate is the center. Take the X size of it, divide it by half and add it to the X position. You now get the exact position of the X edge.

1 Like

Ok, I have chucked that into a function:

function checkBase(base)
	local lowerBoundX = base.Position.X - (base.Size.X / 2)
	local upperBoundX = base.Position.X + (base.Size.X / 2)
	
	local lowerBoundZ = base.Position.Z - (base.Size.Z / 2)
	local upperBoundZ = base.Position.Z + (base.Size.Z / 2)
	
	return lowerBoundX, upperBoundX, lowerBoundZ, upperBoundZ
end

and attaching a print to make sure the number it’s returned are right:

local renderStepped = runService.RenderStepped:Connect(function()
			if not startedPlacingWall then
				local mouseP = mouse.Hit.p
				print(checkBase(playersPlot.Base))
				pole1.CFrame = CFrame.new(roundVector(mouseP + Vector3.new(0, pole1.Size.X/2, 0), gridSize, playersPlot.Base.Position.Y + (pole1.Size.X/2) + 0.5))*CFrame.Angles(0, 0, math.rad(90))
			else
				renderStepped:Disconnect()
			end
		end)

Now if I am right, within the math.clamp, it would be lowerBoundX as the min number and upperBoundX as the max number for the X co-ordinate, and vice versa for the Z. Correct?

With something like this

local lowerX, upperX, lowerZ, upperZ = checkBase(playersPlot.Base)

Not too sure how I would implement the math.clamp it into this line however

pole1.CFrame = CFrame.new(roundVector(mouseP + Vector3.new(0, pole1.Size.X/2, 0), gridSize, playersPlot.Base.Position.Y + (pole1.Size.X/2) + 0.5))*CFrame.Angles(0, 0, math.rad(90))

You would replace MouseP with a new vector3. Here’s the entire line

pole1.CFrame = CFrame.new(roundVector(Vector3.new(math.clamp(mouseP.X, lowerX, upperX), mouseP.Y, math.clamp(mouseP.Z, lowerZ, upperZ)) + Vector3.new(0, pole1.Size.X/2, 0), gridSize, playersPlot.Base.Position.Y + (pole1.Size.X/2) + 0.5))*CFrame.Angles(0, 0, math.rad(90))

This is really long though, so you should probably make some variables instead of stuffing everything in one line. Here’s how that could look:

local mouseClampedP = Vector3.new(
	math.clamp(
		mouseP.X,
		lowerX,
		upperX
	),
	mouseP.Y,
	math.clamp(
		mouseP.Z,
		lowerZ,
		upperZ
	)
)

pole1.CFrame = CFrame.new(
	roundVector(
		
		mouseClampedP
		
		+
		
		Vector3.new(
			0,
			pole1.Size.X / 2,
			0
		),
		gridSize,
		playersPlot.Base.Position.Y 
		+ 
		(pole1.Size.X / 2) + 0.5
	)
) * CFrame.Angles(0, 0, math.rad(90))
3 Likes

Geez, I don’t recall ever hearing of math.clamp. Sounds like a really useful tool!

2 Likes

Works! Thank you :smiley:

1 Like