Building system tries to put objects inside of each other

Hello! I am making a building system for my game and everything seems to be working, except for the fact that when you try and place a block off of another block, then it will think you are trying to build inside the block. This only happens in two directions. The other directions work. Here is a video of the problem:

I suspect this has something to do with how I am rounding the mouse pos to the nearest three.

Here is the script (don’t worry. most of it is UI stuff):

local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local UserInputService = game:GetService("UserInputService")

local building = ReplicatedStorage:WaitForChild("Building")
local blocks = building:WaitForChild("Blocks")
local outline = building:WaitForChild("PlacingOutline")

local player = Players.LocalPlayer
local mouse = player:GetMouse()
local otherstats = player:WaitForChild("otherstats")
local inventory = otherstats:WaitForChild("Inventory")

local gui = player:WaitForChild("PlayerGui"):WaitForChild("MainGui")
local buildMenu = gui:WaitForChild("BuildMenu")
local buildModeButton = buildMenu:WaitForChild("BuildModeButton"):WaitForChild("Button")
local blockList = buildMenu:WaitForChild("Blocks")

local opened = false
local placing = false
local doneWithCurrent = true
local targetPos


local function showPlacingItem(newBlock)
	
	repeat wait() until doneWithCurrent
	doneWithCurrent = false
	newBlock.Parent = workspace
	mouse.TargetFilter = newBlock
	newBlock.Anchored = true
	newBlock.CanCollide = false

	placing = true
	itemBeingPlaced = newBlock

	outline.Parent = newBlock
	outline.Adornee = newBlock
	
	repeat
		wait()
		local mousePos = mouse.Hit.Position
		targetPos = Vector3.new(math.round((mousePos.X) / 3) * 3, math.floor(mousePos.Y / 3) * 3 + newBlock.Size.Y / 2, math.round(mousePos.Z / 3) * 3) + Vector3.new(0, newBlock.Size.Y / 2, 0)
		newBlock.CFrame = CFrame.new(targetPos)
	until itemBeingPlaced ~= newBlock
	doneWithCurrent = true
	
end


local function placeCurrentItem()
	
	local block = itemBeingPlaced
	itemBeingPlaced = nil
	block.CanCollide = true
	block.Position = targetPos
	local newBlock = blocks:WaitForChild(block.Name):Clone()
	showPlacingItem(newBlock)
	
end


local function input(playerInput)
	
	if ((playerInput.UserInputType == Enum.UserInputType.MouseButton1) or (playerInput.UserInputType == Enum.UserInputType.Touch)) and playerInput.UserInputState == Enum.UserInputState.Begin then
		
		if placing then

			placeCurrentItem()

		end
		
	end
	
end


local function addInventory()
	for _, block in pairs(inventory:GetChildren()) do
		local ui = Instance.new("Frame", blockList)
		ui.Name = "Block"
		ui.Size = UDim2.new(1, 0, 1, 0)
		ui.BackgroundColor3 = Color3.fromRGB(255, 255, 255)
		local aspect = Instance.new("UIAspectRatioConstraint", ui)
		aspect.DominantAxis = Enum.DominantAxis.Height
		local corner = Instance.new("UICorner", ui)
		corner.CornerRadius = UDim.new(0, 8)
		local padding = Instance.new("UIPadding", ui)
		padding.PaddingTop = UDim.new(0, 5)
		padding.PaddingBottom = UDim.new(0, 5)
		padding.PaddingLeft = UDim.new(0, 5)
		padding.PaddingRight = UDim.new(0, 5)
		local viewport = Instance.new("ViewportFrame", ui)
		viewport.BackgroundTransparency = 1
		viewport.Size = UDim2.new(1, 0, 1, 0)
		local amount = Instance.new("TextLabel", ui)
		amount.Name = "Amount"
		amount.BackgroundTransparency = 1
		amount.Size = UDim2.new(1, 0, 0.3, 0)
		amount.Position = UDim2.new(0, 0, 1, 0)
		amount.Font = Enum.Font.GothamBold
		amount.TextScaled = true
		amount.AnchorPoint = Vector2.new(0, 1)
		amount.TextXAlignment = Enum.TextXAlignment.Right
		amount.TextYAlignment = Enum.TextYAlignment.Bottom
		local button = Instance.new("TextButton", ui)
		button.Size = UDim2.new(1, 0, 1, 0)
		button.BackgroundTransparency = 1
		button.Text = ""

		amount.Text = "x" .. block.Value
		
		local previewPart = blocks:WaitForChild(block.Name):Clone()
		previewPart.Parent = viewport
		previewPart.Position = Vector3.new(0, 0, 0)
		local camZoom = previewPart:GetAttribute("CameraZoom")
		local camera = Instance.new("Camera", viewport)
		camera.FieldOfView = 70
		camera.CFrame = CFrame.new(Vector3.new(camZoom, camZoom - 0.5, camZoom), Vector3.new(0, 0, 0))
		viewport.CurrentCamera = camera
		
		button.Activated:Connect(function()
			
			local newBlock = previewPart:Clone()
			showPlacingItem(newBlock)
			
		end)
		
	end
end


local function toggleMenu()
	if opened then
		opened = false
		local startPos = UDim2.new(0.5, 0, 1, 0)
		local endPos = UDim2.new(0.5, 0, 1, 90)

		buildMenu.Position = startPos
		buildMenu:TweenPosition(endPos, Enum.EasingDirection.Out, Enum.EasingStyle.Bounce)
	else
		addInventory()
		opened = true
		local startPos = UDim2.new(0.5, 0, 1, 90)
		local endPos = UDim2.new(0.5, 0, 1, 0)

		buildMenu.Position = startPos
		buildMenu:TweenPosition(endPos, Enum.EasingDirection.Out, Enum.EasingStyle.Bounce)
	end
end


buildModeButton.Activated:Connect(toggleMenu)
UserInputService.InputBegan:Connect(input)

Any help is greatly appreciated!

Hello! I am making a building system for my game and everything seems to be working, except for the fact that when you try and place a block off of another block, then it will think you are trying to build inside the block. This only happens in two directions. The other directions work. Here is a video of the problem:

What is the reason behind using math.floor with Y and math.round for the other 2 directions? The calculations seem to be inconsistent for each axis.

Because the y will have to round down for it to feel consistent. I don’t want it so that if a player hovers their mouse slightly over the middle of a block it suddenly tries to go on top of the block.

And when I said two directions I meant that it worked in one X direction and one Z direction (as in it only works with positive X and Z, not negative)

I don’t want it so that if a player hovers their mouse slightly over the middle of a block it suddenly tries to go on top of the block.

You’re already using mouse.Hit.Position, which will give you nil if the cursor points to nothing.

I don’t really understand what you mean, but there is no problem with the Y position of the blocks.

I explained that what you said is not possible due to the method you were using. mouse.Hit will not stop it’s cast on nothing.

Since it works on 2 directions and not the others, the problem is most probably from your grid part (snapping to place to make it look like its following a grid)

Try using the same method you use for Y. Since that works

I’ve already tried math.floor, math.ceil, and math.round.

Fixed it! I just had to make the blocks have a 3.01 size instead of 3.