[HELP] Grid System Collision Problems

Placement System Collision Problems

I’m making a lumber tycoon 2 style placement system for a sandbox game and I’ve been having some problems with the collisions. Currently the dummy block (the preview of the where the block will be) has only some collisions with the parts so I’ve tried using code to determine the targeted parts hight then adding that to the CFrame to put the part on top of the targeted block.

The main problem with that fix is that its very buggy, only works half the time and that it just doesn’t want to work when I try tilting and rotating the block. It works fine when I don’t tilt my block and if I use just a simple block. Here is a video of the problem and bellow is my current version of my script.

And yes I know the code is very inefficient, so please don’t hate too much.

Code (200 Lines)
-- Post Closed

So my main question is, how would I make it so that the part has collisions with the other parts (like it does at the start of the video) with all shapes/rotations?

Any help is appreciated

1 Like

you can make a region3 of the part and check if any part is touching it

function PartToRegion3(part)
	local abs = math.abs

	local cf = part.CFrame 
	local size = part.Size - Vector3.new(0.1,0.1,0.1) 
	local sx, sy, sz = size.X, size.Y, size.Z 

	local x, y, z, R00, R01, R02, R10, R11, R12, R20, R21, R22 = cf:components()

	local wsx = 0.5 * (abs(R00) * sx + abs(R01) * sy + abs(R02) * sz)
	local wsy = 0.5 * (abs(R10) * sx + abs(R11) * sy + abs(R12) * sz)
	local wsz = 0.5 * (abs(R20) * sx + abs(R21) * sy + abs(R22) * sz)

	local minx = x - wsx
	local miny = y - wsy
	local minz = z - wsz

	local maxx = x + wsx
	local maxy = y + wsy
	local maxz = z + wsz

	local minv, maxv = Vector3.new(minx, miny, minz), Vector3.new(maxx, maxy, maxz)
	return Region3.new(minv, maxv)
end

local PartsTouching = 0
local region3 = PartToRegion3(part)
PartsTouching = #workspace:FindPartsInRegion3(region3, part)

you can place the function before the findSide function and place the

local PartsTouching = 0
local region3 = PartToRegion3(part)
PartsTouching = #workspace:FindPartsInRegion3(region3, part)

in the renderstepped and then also put this is the renderstepped:

If PartsTouching ~= 0 then CanPlace == false else CanPlace == true end

make a variable called CanPlace make sure its a boolean
ok so now in the inputbegan event under the if enum.keycode.E put this:

If CanPlace == false then return

Stuff To Make Sure of:

  1. Make sure CanPlace is a global variable (Basically make the variable on line 1)
    imma send the full script in a second please waIT
local CanPlace = false
local Player = game.Players.LocalPlayer
local workspace = game.Workspace
local rot = 90
local plot = game.Workspace.plot
local gsize = 0.5

function PartToRegion3(part)
	local abs = math.abs

	local cf = part.CFrame 
	local size = part.Size - Vector3.new(0.1,0.1,0.1) 
	local sx, sy, sz = size.X, size.Y, size.Z 

	local x, y, z, R00, R01, R02, R10, R11, R12, R20, R21, R22 = cf:components()

	local wsx = 0.5 * (abs(R00) * sx + abs(R01) * sy + abs(R02) * sz)
	local wsy = 0.5 * (abs(R10) * sx + abs(R11) * sy + abs(R12) * sz)
	local wsz = 0.5 * (abs(R20) * sx + abs(R21) * sy + abs(R22) * sz)

	local minx = x - wsx
	local miny = y - wsy
	local minz = z - wsz

	local maxx = x + wsx
	local maxy = y + wsy
	local maxz = z + wsz

	local minv, maxv = Vector3.new(minx, miny, minz), Vector3.new(maxx, maxy, maxz)
	return Region3.new(minv, maxv)
end

function findSide(DummyBlock)
	local cf=DummyBlock.CFrame
	local cs={side=nil,y=-2}
	if cf.lookVector.Y>cs.y then cs.side="BackSurface" cs.y=cf.lookVector.Y end
	if -cf.lookVector.Y>cs.y then cs.side="FrontSurface" cs.y=-cf.lookVector.Y end
	if cf.rightVector.Y>cs.y then cs.side="LeftSurface" cs.y=cf.rightVector.Y end
	if -cf.rightVector.Y>cs.y then cs.side="RightSurface" cs.y=-cf.rightVector.Y end
	if cf.upVector.Y>cs.y then cs.side="BottomSurface" cs.y=cf.upVector.Y end
	if -cf.upVector.Y>cs.y then cs.side="TopSurface" cs.y=-cf.upVector.Y end
	return cs.side
end

local UserInputService = game:GetService("UserInputService")
local Mouse = Player:GetMouse()
Mouse.TargetFilter = game.Workspace:FindFirstChild(Player)
local RunService = game:GetService("RunService")


local DummyBlock = game.ReplicatedStorage.Block:Clone(); DummyBlock.CFrame = CFrame.new(0,0,0); DummyBlock.Parent = workspace; DummyBlock.Name = "DummyBlock"; DummyBlock.Transparency = 0.5; DummyBlock.CanCollide = false; DummyBlock.Anchored = true;DummyBlock.Color = Color3.fromRGB(0, 68, 216)
Mouse.TargetFilter = DummyBlock
local function roundToStep(initialValue,step)
	local roundedValue = math.floor(initialValue/step)*step
	return roundedValue --Returns 60
end

RunService.RenderStepped:Connect(function()
	local PartsTouching = 0
	local region3 = PartToRegion3(DummyBlock)
	PartsTouching = #workspace:FindPartsInRegion3(region3)
	if findSide(DummyBlock) == "LeftSurface" then
		if Mouse.TargetSurface == Enum.NormalId.Front then
			DummyBlock.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize), roundToStep(Mouse.Hit.Position.Y, gsize)+DummyBlock.Size.X/2, roundToStep(Mouse.Hit.Position.Z, gsize)-DummyBlock.Size.Z/2)
		elseif Mouse.TargetSurface == Enum.NormalId.Back then
			DummyBlock.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize), roundToStep(Mouse.Hit.Position.Y, gsize)+DummyBlock.Size.X/2, roundToStep(Mouse.Hit.Position.Z, gsize)+DummyBlock.Size.Z/2)
		elseif Mouse.TargetSurface == Enum.NormalId.Left then
			DummyBlock.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize), roundToStep(Mouse.Hit.Position.Y, gsize)-DummyBlock.Size.X/2, roundToStep(Mouse.Hit.Position.Z, gsize))
		elseif Mouse.TargetSurface == Enum.NormalId.Right then
			DummyBlock.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize), roundToStep(Mouse.Hit.Position.Y, gsize)+DummyBlock.Size.X/2, roundToStep(Mouse.Hit.Position.Z, gsize))
		elseif Mouse.TargetSurface == Enum.NormalId.Top and Mouse.Target.Name == "Block" then
			DummyBlock.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize)-DummyBlock.Size.Y/2, roundToStep(Mouse.Hit.Position.Y, gsize), roundToStep(Mouse.Hit.Position.Z, gsize))
		elseif Mouse.TargetSurface == Enum.NormalId.Bottom then
			DummyBlock.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize)+DummyBlock.Size.Y/2, roundToStep(Mouse.Hit.Position.Y, gsize), roundToStep(Mouse.Hit.Position.Z, gsize))
		else
			DummyBlock.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize), roundToStep(Mouse.Hit.Position.Y, gsize)+DummyBlock.Size.X/2, roundToStep(Mouse.Hit.Position.Z, gsize))
		end
	elseif findSide(DummyBlock) == "RightSurface" then
		if Mouse.TargetSurface == Enum.NormalId.Front then
			DummyBlock.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize), roundToStep(Mouse.Hit.Position.Y, gsize)+DummyBlock.Size.X/2, roundToStep(Mouse.Hit.Position.Z, gsize)-DummyBlock.Size.Z/2)
		elseif Mouse.TargetSurface == Enum.NormalId.Back then
			DummyBlock.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize), roundToStep(Mouse.Hit.Position.Y, gsize)+DummyBlock.Size.X/2, roundToStep(Mouse.Hit.Position.Z, gsize)+DummyBlock.Size.Z/2)
		elseif Mouse.TargetSurface == Enum.NormalId.Left then
			DummyBlock.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize), roundToStep(Mouse.Hit.Position.Y, gsize)-DummyBlock.Size.X/2, roundToStep(Mouse.Hit.Position.Z, gsize))
		elseif Mouse.TargetSurface == Enum.NormalId.Right then
			DummyBlock.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize), roundToStep(Mouse.Hit.Position.Y, gsize)+DummyBlock.Size.X/2, roundToStep(Mouse.Hit.Position.Z, gsize))
		elseif Mouse.TargetSurface == Enum.NormalId.Top and Mouse.Target.Name == "Block" then
			DummyBlock.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize)-DummyBlock.Size.Y/2, roundToStep(Mouse.Hit.Position.Y, gsize), roundToStep(Mouse.Hit.Position.Z, gsize))
		elseif Mouse.TargetSurface == Enum.NormalId.Bottom then
			DummyBlock.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize)+DummyBlock.Size.Y/2, roundToStep(Mouse.Hit.Position.Y, gsize), roundToStep(Mouse.Hit.Position.Z, gsize))
		else
			DummyBlock.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize), roundToStep(Mouse.Hit.Position.Y, gsize)+DummyBlock.Size.X/2, roundToStep(Mouse.Hit.Position.Z, gsize))
		end
	elseif findSide(DummyBlock) == "BottomSurface" then
		if Mouse.TargetSurface == Enum.NormalId.Right then
			DummyBlock.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize)+DummyBlock.Size.X/2, roundToStep(Mouse.Hit.Position.Y, gsize)+DummyBlock.Size.Y/2, roundToStep(Mouse.Hit.Position.Z, gsize))
		elseif Mouse.TargetSurface == Enum.NormalId.Left then
			DummyBlock.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize)-DummyBlock.Size.X/2, roundToStep(Mouse.Hit.Position.Y, gsize)+DummyBlock.Size.Y/2, roundToStep(Mouse.Hit.Position.Z, gsize))
		elseif Mouse.TargetSurface == Enum.NormalId.Front then
			DummyBlock.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize), roundToStep(Mouse.Hit.Position.Y, gsize)+DummyBlock.Size.Y/2, roundToStep(Mouse.Hit.Position.Z, gsize)-DummyBlock.Size.Z/2)
		elseif Mouse.TargetSurface == Enum.NormalId.Back then
			DummyBlock.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize), roundToStep(Mouse.Hit.Position.Y, gsize)+DummyBlock.Size.Y/2, roundToStep(Mouse.Hit.Position.Z, gsize)+DummyBlock.Size.Z/2)
		else
			DummyBlock.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize), roundToStep(Mouse.Hit.Position.Y, gsize)+DummyBlock.Size.Y/2, roundToStep(Mouse.Hit.Position.Z, gsize))
		end
	elseif findSide(DummyBlock) == "TopSurface" then
		if Mouse.TargetSurface == Enum.NormalId.Right then
			DummyBlock.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize)-DummyBlock.Size.X/2, roundToStep(Mouse.Hit.Position.Y, gsize)+DummyBlock.Size.Y/2, roundToStep(Mouse.Hit.Position.Z, gsize))
		elseif Mouse.TargetSurface == Enum.NormalId.Left then
			DummyBlock.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize)+DummyBlock.Size.X/2, roundToStep(Mouse.Hit.Position.Y, gsize)+DummyBlock.Size.Y/2, roundToStep(Mouse.Hit.Position.Z, gsize))
		elseif Mouse.TargetSurface == Enum.NormalId.Front then
			DummyBlock.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize), roundToStep(Mouse.Hit.Position.Y, gsize)+DummyBlock.Size.Y/2, roundToStep(Mouse.Hit.Position.Z, gsize)-DummyBlock.Size.Z/2)
		elseif Mouse.TargetSurface == Enum.NormalId.Back then
			DummyBlock.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize), roundToStep(Mouse.Hit.Position.Y, gsize)+DummyBlock.Size.Y/2, roundToStep(Mouse.Hit.Position.Z, gsize)+DummyBlock.Size.Z/2)
		else
			DummyBlock.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize), roundToStep(Mouse.Hit.Position.Y, gsize)+DummyBlock.Size.Y/2, roundToStep(Mouse.Hit.Position.Z, gsize))
		end
	elseif findSide(DummyBlock) == "FrontSurface" then
		if Mouse.TargetSurface == Enum.NormalId.Right then
			DummyBlock.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize), roundToStep(Mouse.Hit.Position.Y, gsize), roundToStep(Mouse.Hit.Position.Y, gsize))
		elseif Mouse.TargetSurface == Enum.NormalId.Left then
			DummyBlock.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize), roundToStep(Mouse.Hit.Position.Y, gsize), roundToStep(Mouse.Hit.Position.Y, gsize))
		elseif Mouse.TargetSurface == Enum.NormalId.Front then
			DummyBlock.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize), roundToStep(Mouse.Hit.Position.Y, gsize), roundToStep(Mouse.Hit.Position.Z, gsize))
		elseif Mouse.TargetSurface == Enum.NormalId.Back then
			DummyBlock.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize), roundToStep(Mouse.Hit.Position.Y, gsize), roundToStep(Mouse.Hit.Position.Z, gsize))
		elseif Mouse.TargetSurface == Enum.NormalId.Top and Mouse.Target.Name == "Block" then
			DummyBlock.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize), roundToStep(Mouse.Hit.Position.Y, gsize), roundToStep(Mouse.Hit.Position.Z, gsize))
		elseif Mouse.TargetSurface == Enum.NormalId.Bottom then
			DummyBlock.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize), roundToStep(Mouse.Hit.Position.Y, gsize), roundToStep(Mouse.Hit.Position.Z, gsize))
		else
			DummyBlock.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize), roundToStep(Mouse.Hit.Position.Y, gsize)+DummyBlock.Size.Z/2, roundToStep(Mouse.Hit.Position.Z, gsize))
		end
	end
	--[[if Mouse.TargetSurface == Enum.NormalId.Right then
		DummyBlock.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize)+DummyBlock.Size.X/2, roundToStep(Mouse.Hit.Position.Y, gsize)+DummyBlock.Size.Y/2, roundToStep(Mouse.Hit.Position.Z, gsize))
	elseif Mouse.TargetSurface == Enum.NormalId.Left then
		DummyBlock.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize)-DummyBlock.Size.X/2, roundToStep(Mouse.Hit.Position.Y, gsize)+DummyBlock.Size.Y/2, roundToStep(Mouse.Hit.Position.Z, gsize))
	elseif Mouse.TargetSurface == Enum.NormalId.Front then
		DummyBlock.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize), roundToStep(Mouse.Hit.Position.Y, gsize)+DummyBlock.Size.Y/2, roundToStep(Mouse.Hit.Position.Z, gsize)-DummyBlock.Size.Z/2)
	elseif Mouse.TargetSurface == Enum.NormalId.Back then
		DummyBlock.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize), roundToStep(Mouse.Hit.Position.Y, gsize)+DummyBlock.Size.Y/2, roundToStep(Mouse.Hit.Position.Z, gsize)+DummyBlock.Size.Z/2)
	else
		DummyBlock.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize), roundToStep(Mouse.Hit.Position.Y, gsize)+DummyBlock.Size.Y/2, roundToStep(Mouse.Hit.Position.Z, gsize))
	end--]]
	if PartsTouching ~= 0 then CanPlace = false else CanPlace = true end
	wait(0.01)
end)

UserInputService.InputBegan:Connect(function(keycode)
	if keycode.KeyCode == Enum.KeyCode.E and CanPlace == true then
		print(findSide(DummyBlock))
		print(Mouse.TargetSurface)
		local look = Mouse.Target.CFrame.LookVector.X
		local colorV = script.Parent.Parent.Color.Value
		local result = game.Workspace:Raycast(DummyBlock.Position,Vector3.new(0,-10,0))
		local Block = game.ReplicatedStorage.Block:Clone(); Block.Parent = workspace.plotItems; Block.Anchored = true;Block.BrickColor = BrickColor.new(colorV)
		Block.Orientation = DummyBlock.Orientation
		--[[if findSide(DummyBlock) == "LeftSurface" or findSide(DummyBlock) == "RightSurface" then
			Block.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize), roundToStep(Mouse.Hit.Position.Y, gsize)+DummyBlock.Size.X/2, roundToStep(Mouse.Hit.Position.Z, gsize))
		end--]]
		if findSide(DummyBlock) == "LeftSurface" then
			if Mouse.TargetSurface == Enum.NormalId.Front then
				Block.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize), roundToStep(Mouse.Hit.Position.Y, gsize)+Block.Size.X/2, roundToStep(Mouse.Hit.Position.Z, gsize)-Block.Size.Z/2)
			elseif Mouse.TargetSurface == Enum.NormalId.Back then
				Block.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize), roundToStep(Mouse.Hit.Position.Y, gsize)+Block.Size.X/2, roundToStep(Mouse.Hit.Position.Z, gsize)+Block.Size.Z/2)
			elseif Mouse.TargetSurface == Enum.NormalId.Left then
				Block.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize), roundToStep(Mouse.Hit.Position.Y, gsize)-Block.Size.X/2, roundToStep(Mouse.Hit.Position.Z, gsize))
			elseif Mouse.TargetSurface == Enum.NormalId.Right then
				Block.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize), roundToStep(Mouse.Hit.Position.Y, gsize)+Block.Size.X/2, roundToStep(Mouse.Hit.Position.Z, gsize))
			elseif Mouse.TargetSurface == Enum.NormalId.Top and Mouse.Target.Name == "Block" then
				Block.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize)-Block.Size.Y/2, roundToStep(Mouse.Hit.Position.Y, gsize), roundToStep(Mouse.Hit.Position.Z, gsize))
			elseif Mouse.TargetSurface == Enum.NormalId.Bottom then
				Block.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize)+Block.Size.Y/2, roundToStep(Mouse.Hit.Position.Y, gsize), roundToStep(Mouse.Hit.Position.Z, gsize))
			else
				Block.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize), roundToStep(Mouse.Hit.Position.Y, gsize)+Block.Size.X/2, roundToStep(Mouse.Hit.Position.Z, gsize))
			end
		elseif findSide(DummyBlock) == "RightSurface" then
			if Mouse.TargetSurface == Enum.NormalId.Front then
				Block.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize), roundToStep(Mouse.Hit.Position.Y, gsize)+Block.Size.X/2, roundToStep(Mouse.Hit.Position.Z, gsize)-Block.Size.Z/2)
			elseif Mouse.TargetSurface == Enum.NormalId.Back then
				Block.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize), roundToStep(Mouse.Hit.Position.Y, gsize)+Block.Size.X/2, roundToStep(Mouse.Hit.Position.Z, gsize)+Block.Size.Z/2)
			elseif Mouse.TargetSurface == Enum.NormalId.Left then
				Block.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize), roundToStep(Mouse.Hit.Position.Y, gsize)-Block.Size.X/2, roundToStep(Mouse.Hit.Position.Z, gsize))
			elseif Mouse.TargetSurface == Enum.NormalId.Right then
				Block.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize), roundToStep(Mouse.Hit.Position.Y, gsize)+Block.Size.X/2, roundToStep(Mouse.Hit.Position.Z, gsize))
			elseif Mouse.TargetSurface == Enum.NormalId.Top and Mouse.Target.Name == "Block" then
				Block.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize)-Block.Size.Y/2, roundToStep(Mouse.Hit.Position.Y, gsize), roundToStep(Mouse.Hit.Position.Z, gsize))
			elseif Mouse.TargetSurface == Enum.NormalId.Bottom then
				Block.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize)+Block.Size.Y/2, roundToStep(Mouse.Hit.Position.Y, gsize), roundToStep(Mouse.Hit.Position.Z, gsize))
			else
				Block.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize), roundToStep(Mouse.Hit.Position.Y, gsize)+Block.Size.X/2, roundToStep(Mouse.Hit.Position.Z, gsize))
			end
		elseif findSide(DummyBlock) == "BottomSurface" then
			if Mouse.TargetSurface == Enum.NormalId.Right then
				Block.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize)+Block.Size.X/2, roundToStep(Mouse.Hit.Position.Y, gsize)+Block.Size.Y/2, roundToStep(Mouse.Hit.Position.Z, gsize))
			elseif Mouse.TargetSurface == Enum.NormalId.Left then
				Block.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize)-Block.Size.X/2, roundToStep(Mouse.Hit.Position.Y, gsize)+Block.Size.Y/2, roundToStep(Mouse.Hit.Position.Z, gsize))
			elseif Mouse.TargetSurface == Enum.NormalId.Front then
				Block.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize), roundToStep(Mouse.Hit.Position.Y, gsize)+Block.Size.Y/2, roundToStep(Mouse.Hit.Position.Z, gsize)-Block.Size.Z/2)
			elseif Mouse.TargetSurface == Enum.NormalId.Back then
				Block.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize), roundToStep(Mouse.Hit.Position.Y, gsize)+Block.Size.Y/2, roundToStep(Mouse.Hit.Position.Z, gsize)+Block.Size.Z/2)
			else
				Block.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize), roundToStep(Mouse.Hit.Position.Y, gsize)+Block.Size.Y/2, roundToStep(Mouse.Hit.Position.Z, gsize))
			end
		elseif findSide(DummyBlock) == "TopSurface" then
			if Mouse.TargetSurface == Enum.NormalId.Right then
				Block.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize)-Block.Size.X/2, roundToStep(Mouse.Hit.Position.Y, gsize)+Block.Size.Y/2, roundToStep(Mouse.Hit.Position.Z, gsize))
			elseif Mouse.TargetSurface == Enum.NormalId.Left then
				Block.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize)+Block.Size.X/2, roundToStep(Mouse.Hit.Position.Y, gsize)+Block.Size.Y/2, roundToStep(Mouse.Hit.Position.Z, gsize))
			elseif Mouse.TargetSurface == Enum.NormalId.Front then
				Block.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize), roundToStep(Mouse.Hit.Position.Y, gsize)+Block.Size.Y/2, roundToStep(Mouse.Hit.Position.Z, gsize)-Block.Size.Z/2)
			elseif Mouse.TargetSurface == Enum.NormalId.Back then
				Block.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize), roundToStep(Mouse.Hit.Position.Y, gsize)+Block.Size.Y/2, roundToStep(Mouse.Hit.Position.Z, gsize)+Block.Size.Z/2)
			else
				Block.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize), roundToStep(Mouse.Hit.Position.Y, gsize)+Block.Size.Y/2, roundToStep(Mouse.Hit.Position.Z, gsize))
			end
		elseif findSide(DummyBlock) == "FrontSurface" then
			if Mouse.TargetSurface == Enum.NormalId.Right then
				Block.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize), roundToStep(Mouse.Hit.Position.Y, gsize), roundToStep(Mouse.Hit.Position.Y, gsize))
			elseif Mouse.TargetSurface == Enum.NormalId.Left then
				Block.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize), roundToStep(Mouse.Hit.Position.Y, gsize), roundToStep(Mouse.Hit.Position.Y, gsize))
			elseif Mouse.TargetSurface == Enum.NormalId.Front then
				Block.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize), roundToStep(Mouse.Hit.Position.Y, gsize), roundToStep(Mouse.Hit.Position.Z, gsize))
			elseif Mouse.TargetSurface == Enum.NormalId.Back then
				Block.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize), roundToStep(Mouse.Hit.Position.Y, gsize), roundToStep(Mouse.Hit.Position.Z, gsize))
			elseif Mouse.TargetSurface == Enum.NormalId.Top and Mouse.Target.Name == "Block" then
				Block.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize), roundToStep(Mouse.Hit.Position.Y, gsize), roundToStep(Mouse.Hit.Position.Z, gsize))
			elseif Mouse.TargetSurface == Enum.NormalId.Bottom then
				Block.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize), roundToStep(Mouse.Hit.Position.Y, gsize), roundToStep(Mouse.Hit.Position.Z, gsize))
			else
				Block.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize), roundToStep(Mouse.Hit.Position.Y, gsize)+Block.Size.Z/2, roundToStep(Mouse.Hit.Position.Z, gsize))
			end
		end
		--[[if result.Instance == game.Workspace.plot or result.Instance.Name == "Block" then
			if Mouse.TargetSurface == Enum.NormalId.Right then
				Block.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize)+DummyBlock.Size.X/2, roundToStep(Mouse.Hit.Position.Y, gsize)+DummyBlock.Size.Y/2, roundToStep(Mouse.Hit.Position.Z, gsize))
			elseif Mouse.TargetSurface == Enum.NormalId.Left then
				Block.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize)-DummyBlock.Size.X/2, roundToStep(Mouse.Hit.Position.Y, gsize)+DummyBlock.Size.Y/2, roundToStep(Mouse.Hit.Position.Z, gsize))
			elseif Mouse.TargetSurface == Enum.NormalId.Front then
				Block.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize), roundToStep(Mouse.Hit.Position.Y, gsize)+DummyBlock.Size.Y/2, roundToStep(Mouse.Hit.Position.Z, gsize)-DummyBlock.Size.Z/2)
			elseif Mouse.TargetSurface == Enum.NormalId.Back then
				Block.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize), roundToStep(Mouse.Hit.Position.Y, gsize)+DummyBlock.Size.Y/2, roundToStep(Mouse.Hit.Position.Z, gsize)+DummyBlock.Size.Z/2)
			else
				Block.Position = Vector3.new(roundToStep(Mouse.Hit.Position.X, gsize), roundToStep(Mouse.Hit.Position.Y, gsize)+DummyBlock.Size.Y/2, roundToStep(Mouse.Hit.Position.Z, gsize))
			end
		else
			Block:Destroy()
			DummyBlock.Color = Color3.fromRGB(255, 0, 0)
			wait(0.5)
			DummyBlock.Color = Color3.fromRGB(0, 68, 216)
		end--]]
		wait()
	elseif keycode.KeyCode == Enum.KeyCode.R then
		DummyBlock.CFrame = DummyBlock.CFrame * CFrame.Angles(0, math.rad(rot) ,0)
		wait()
	elseif keycode.KeyCode == Enum.KeyCode.T then
		DummyBlock.CFrame = DummyBlock.CFrame * CFrame.Angles(0 ,0 ,math.rad(rot))
		wait()
	end
end)

here is the full script also the method you’re doing is super ineffecient
i’ve done the same but much better with all kinds of effects like tweening the part to the position i want and placement effect in only 136 lines

Yeah Ik, its just I only really know the basic stuff of cframe. Is the script you sent the one that you optimised?

local player = game:GetService('Players').LocalPlayer
local mouse = player:GetMouse()

local UIS = game:GetService('UserInputService')
local RS = game:GetService('RunService')
local TS = game:GetService('TweenService')

local oldpos = nil
local building = false

local isrotating = false

local PartsTouching = {}

local LastOrientation = Vector3.new(0,0,0)

local SelectedPart = script.Table

local floor = 0

local BuildZone = workspace.Plots:WaitForChild(player.Name .. "'s plot")

BuildZone.Touched:Connect(function() end)

function IsPartInZone(Part)
	local touching = BuildZone:GetTouchingParts()
	for i=1,#touching do
		if touching[i] == Part then
			return true
		end
	end
	return false
end

function PartToRegion3(part)
	local abs = math.abs

	local cf = part.CFrame 
	local size = part.Size - Vector3.new(0.1,0.1,0.1) 
	local sx, sy, sz = size.X, size.Y, size.Z 

	local x, y, z, R00, R01, R02, R10, R11, R12, R20, R21, R22 = cf:components()

	local wsx = 0.5 * (abs(R00) * sx + abs(R01) * sy + abs(R02) * sz)
	local wsy = 0.5 * (abs(R10) * sx + abs(R11) * sy + abs(R12) * sz)
	local wsz = 0.5 * (abs(R20) * sx + abs(R21) * sy + abs(R22) * sz)

	local minx = x - wsx
	local miny = y - wsy
	local minz = z - wsz

	local maxx = x + wsx
	local maxy = y + wsy
	local maxz = z + wsz

	local minv, maxv = Vector3.new(minx, miny, minz), Vector3.new(maxx, maxy, maxz)
	return Region3.new(minv, maxv)
end

UIS.InputBegan:Connect(function(input)
	if input.KeyCode == Enum.KeyCode.E and building == false then
		building = true
		local IsInZone = false
		local TargetPosition = Vector3.new(0,0,0)
		local mousefunc
		local part = SelectedPart:Clone()
		part.Parent = workspace.Builds
		mouse.TargetFilter = workspace.Builds
		local function RoundVector(X,Y,Z)
			return Vector3.new(math.round(X),math.round(Y),math.round(Z)) + Vector3.new(0,part.Size.Y/2,0)
		end
		local mousepos = mouse.Hit.Position
		part.Position = RoundVector(mousepos.X,floor * 8,mousepos.Z)
		part.Orientation = LastOrientation
		spawn(function()
			while building do
				local mousepos = mouse.Hit.Position
				local newpos = RoundVector(mousepos.X,floor * 8,mousepos.Z)
				if oldpos ~= newpos then
					TargetPosition = newpos
					local tween = TS:Create(part, TweenInfo.new(0.05,Enum.EasingStyle.Quad,Enum.EasingDirection.In), {Position = newpos})
					tween:Play()
					tween.Completed:Wait()
				end
				oldpos = newpos
				local region3 = PartToRegion3(part)
				PartsTouching = workspace:FindPartsInRegion3(region3, part)
				if table.find(PartsTouching, workspace.Baseplate) then
					table.remove(PartsTouching,table.find(PartsTouching, workspace.Baseplate))
				end
				if table.find(PartsTouching, workspace.Builds.BuildZone) then
					table.remove(PartsTouching,table.find(PartsTouching, workspace.Builds.BuildZone))
				end
				if #PartsTouching > 0 then
					part.BrickColor = BrickColor.new('Really red')
				end
				IsInZone = IsPartInZone(part)
				if not IsInZone then
					part.BrickColor = BrickColor.new('Really red')
				elseif IsInZone and #PartsTouching == 0 then
					part.BrickColor = BrickColor.new('Lime green')
				end
				print(#PartsTouching, PartsTouching, IsInZone)
				task.wait()
			end
		end)
		local InputAwait = UIS.InputBegan:Connect(function(input)
			if input.KeyCode == Enum.KeyCode.R and isrotating == false then
				isrotating = true
				LastOrientation = part.Orientation + Vector3.new(0,90,0)
				local tween = TS:Create(part, TweenInfo.new(0.1,Enum.EasingStyle.Quad,Enum.EasingDirection.In), {Orientation = (part.Orientation + Vector3.new(0,90,0))})
				tween:Play()
				tween.Completed:Wait()
				isrotating = false
			end
		end)
		mousefunc = mouse.Button1Down:Connect(function()
			PartsTouching = workspace:FindPartsInRegion3(PartToRegion3(part), part)
			if table.find(PartsTouching, workspace.Baseplate) then
				table.remove(PartsTouching,table.find(PartsTouching, workspace.Baseplate))
			end
			if table.find(PartsTouching, workspace.Builds.BuildZone) then
				table.remove(PartsTouching,table.find(PartsTouching, workspace.Builds.BuildZone))
			end
			if #PartsTouching == 0 and IsInZone then
				game.ReplicatedStorage.Place:FireServer((CFrame.new(TargetPosition) * CFrame.Angles(0, math.rad(LastOrientation.y), 0)))
				part:Destroy()
				mousefunc:Disconnect()
				InputAwait:Disconnect()
				building = false
			else
				part.BrickColor = BrickColor.new('Really red')
			end
		end)
	end
end)

here is the script im talking about if you wanna read it

floor is basically how high you wanna build multiplied by 8 studs

Thanks, but its giving me a error in the console? Table is not a valid member of local script? (line 17)

edit: I think ik whats wrong

line 17 doesnt even refrence any kind of table are you sure ?
oooh wait ye so the ‘Part’ argument passed has to be a basepart is the DummyBlock a part?

it’s a variable, script.table. Im guessing you want me to put the part that I’m coping?

oh ur talking about my script, so basically you have to set the SelectedPart variable to the part you wanna place and make sure to set the BuildZone variable to a part


Like this? Because this doesn’t give a console error or place something in the workspace?

you should just not use my script since setting it up to your liking is complicated since i have remoteevents and other stuff

Why would you not just use GetPartsInPart()? Converting a part into Region3, then using FindPartsInRegion3 seems pointless when you can just use the part with GetPartsInPart(), also considering that Region3 is Deprecated and shouldn’t be used anymore.