Help with scripting building system

Hi, I’ve been trying to make a building mechanism in my game lately and I can’t seem to figure out how to prevent part’s phasing inside of eachother without collision. My building system is OK, but not foolproof as people can merge parts in wacky way’s that I don’t want them to.

As you can see from this video, the part’s are phasing inside of eachother. Is there a way to make it to where this isn’t possible. I am aware that making the part unanchored would solve this, but the part is updated to the mouses position every frame on the client. (That’s pretty much all of the code).

If anyone could help me it would be greatly appreciated

maybe raycast from part origin (center) to the edge points of the part
local TopMiddle = part.CFrame + (part.CFrame.UpVector * part.Size.Y/2)
local RightMiddle = part.CFrame + (part.CFrame.RightVector * part.Size.X/2)
local BottomMiddle = part.CFrame - (part.CFrame.UpVector * part.Size.Y/2)
local LeftMiddle = part.CFrame - (part.CFrame.RightVector * part.Size.X/2)
starting from the center, adding half of the size will bring you to the edge

placement.rbxl (33.8 KB)

local mouse = game.Players.LocalPlayer:GetMouse()
local ghost = Instance.new("Part")
ghost.Size = Vector3.new(5, 10, 1)
ghost.Transparency = 0.6
ghost.Anchored = true
ghost.CanCollide = false
ghost.Parent = workspace
mouse.TargetFilter = ghost

game:GetService("UserInputService").InputEnded:Connect(function(InputObject, Processed)
	if InputObject.KeyCode == Enum.KeyCode.R then
		ghost.Orientation = ghost.Orientation + Vector3.new(0, 5, 0)
	end
end)


local visParts = {}
while wait() do
	if mouse.Hit then
		for _, visPart in pairs(visParts) do
			visPart:Destroy()
		end
		ghost.Position = mouse.Hit.Position + Vector3.new(0, ghost.Size.Y/2, 0)
		local CFrames = {
			ghost.CFrame + (ghost.CFrame.UpVector * ghost.Size.Y/2),
			ghost.CFrame + (ghost.CFrame.RightVector * ghost.Size.X/2),
			ghost.CFrame - (ghost.CFrame.UpVector * ghost.Size.Y/2),
			ghost.CFrame - (ghost.CFrame.RightVector * ghost.Size.X/2)
		}
		local raycastParams = RaycastParams.new()
		raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
		raycastParams.FilterDescendantsInstances = {ghost}
		local hit = false
		for index, cf in pairs(CFrames) do
			local visPart = Instance.new("Part")
			visPart.Anchored = true
			visPart.CFrame = cf
			visPart.Size = Vector3.new(1,1,1)
			visPart.Name = index
			visPart.CanCollide = false
			visPart.Transparency = .6
			visPart.Color = Color3.fromRGB(60, 1, 255)
			visPart.Parent = ghost
			table.insert(visParts, visPart)
			local r = workspace:Raycast(ghost.Position, cf.Position - ghost.Position, raycastParams)
			if r then
				if r.Instance then
					hit = true
				end
			end
			ghost.Color = hit and Color3.fromRGB(255, 0, 4) or Color3.fromRGB(0, 255, 106)
		end
	end
end

you can add more points for accuracy:
image

		local CFrames = {
			ghost.CFrame + (ghost.CFrame.UpVector * ghost.Size.Y/2),
			ghost.CFrame + (ghost.CFrame.RightVector * ghost.Size.X/2),
			ghost.CFrame - (ghost.CFrame.UpVector * ghost.Size.Y/2),
			ghost.CFrame - (ghost.CFrame.RightVector * ghost.Size.X/2)
		}
		for i = (ghost.Size.Y/2)/5, ghost.Size.Y/2 do
			table.insert(CFrames, ghost.CFrame + (ghost.CFrame.RightVector * ghost.Size.Y/4) + Vector3.new(0, i, 0))
			table.insert(CFrames, ghost.CFrame + (ghost.CFrame.RightVector * ghost.Size.Y/4) + Vector3.new(0, -i, 0))
			
			
			table.insert(CFrames, ghost.CFrame - (ghost.CFrame.RightVector * ghost.Size.Y/4) + Vector3.new(0, i, 0))
			table.insert(CFrames, ghost.CFrame - (ghost.CFrame.RightVector * ghost.Size.Y/4) + Vector3.new(0, -i, 0))
			
			
			table.insert(CFrames, ghost.CFrame + (ghost.CFrame.UpVector * ghost.Size.Y/2) + ghost.CFrame.RightVector * i/2)
			table.insert(CFrames, ghost.CFrame + (ghost.CFrame.UpVector * ghost.Size.Y/2) - ghost.CFrame.RightVector * i/2)
			
			
			table.insert(CFrames, ghost.CFrame - (ghost.CFrame.UpVector * ghost.Size.Y/2) + ghost.CFrame.RightVector * i/2)
			table.insert(CFrames, ghost.CFrame - (ghost.CFrame.UpVector * ghost.Size.Y/2) - ghost.CFrame.RightVector * i/2)
		end

these scripts are rough concepts, re-write them yourself

1 Like

This is such a detailed help for me! Thank you so much!

Wait, hang on. How would I move the part backward though? And for the first part couldn’t I just use GetPartsInPart()?

I wouldnt move the part, just set it red until they move it into a valid spot

if you do want to set it, you can use the point that was triggered to get the distance from the origin and then offset the ghost in the opposite direction and then repeat, if it fails twice in a row just set it red and keep it at mouse hit

you can use whatever you want, I chose raycast
you will want to check if its valid once on the server before placing