How can I make a block building system that can stack on top of eachother?

Hi, lately I’ve been trying to make a building system that snaps to 5 studs. I’ve achieved this quite fine with no bugs but the only problem is is that the blocks wont stack on top of each other. You can kind of think of my building system as it would be in minecraft. I can stack up 2 blocks but then they just start going into eachother and it’s a mess. I’m not sure how to fix this so I came here for answers, here’s my code:

(I also believe that the issue is around where it says PosX PosY and PosZ as that’s where it snaps to a grid.)

mouse.Move:Connect(function()
	local mouseRay = mouse.UnitRay
	
	local rayCastParams = RaycastParams.new()
	rayCastParams.FilterType = Enum.RaycastFilterType.Blacklist
	rayCastParams.FilterDescendantsInstances = {GhostItem, player.Character}
	
	local castRay = workspace:Raycast(mouseRay.Origin, mouseRay.Direction * 500, rayCastParams)
	local ignoreList = {GhostItem, player.Character}
	
	if castRay and castRay.Instance:IsA("BasePart") and math.floor((humRootPart.Position - castRay.Position).Magnitude) <= 20 then
		CanPlace = true
		for i,v in pairs(GhostItem:GetChildren()) do
			v.BrickColor = BrickColor.new("Bright green")
		end
		
		local PosX = math.floor(castRay.Position.X / GridSize) * GridSize
		local PosY = GhostItem.PrimaryPart.Position.Y
		local PosZ = math.floor(castRay.Position.Z / GridSize) * GridSize
		
		GhostItem:SetPrimaryPartCFrame(CFrame.new(PosX,PosY,PosZ))
	else
		CanPlace = false
		for i,v in pairs(GhostItem:GetChildren()) do
			v.BrickColor = BrickColor.new("Really red")
		end
	end
end)

Note that I cut out most of the code because it’s just variables and what not, I also feel like this itself is a big chunk of code to read and attempt to fix let alone 40+ other lines.

3 Likes

Do the boxes stack, if you set PosY to the rounded castRay.Position.Y, instead of the GhostItem.PrimaryPart.Position?

local PosY = math.floor(castRay.Position.Y / GridSize) * GridSize

Since you called the SetPrimaryPartCFrame on the GhostItem, after you already defined PosY, aren’t you disregarding the height at which castRay hit?

Already tried that, the blocks will phase through each other and half of the first block that is placed is in the ground. Though I think I came up with something while writing this, give me a minute.

Edit: my solution did work, what I did is I took the GhostItem’s Size.Y/2 and added it on to castRay.Position.Y. Though if any other issues pop up I’ll reply to this message.

1 Like

What are the sizes of your blocks? If they are too much smaller than your GridSize, then they will be rounded down to the ground instead of up on top of each other.

I ran into an issue that I think is very weird. I’m trying to detect if the GhostItem is inside of another block and if so GhostItem can’t be placed. But for some reason the .Touched event wont trigger when it is inside of another part but it will fire when it is inside the player for example. I find this to be very weird, I’m trying to detect if the GhostItem is being touched by another part on the server but GhostItem is handled on the client, i’m not sure if this is a limitation of the .Touched event.

If you are teleporting bricks on top of the GhostPart, it will not constantly fire the .Touched event. .Touched only fires regularly when an object moves onto the part.

Have you tried substituting .Touched for a Region3, and FindPartsInRegion3, or possibly GetTouchingParts?

I am not very familiar with Region3’s as I haven’t ever used them. How would I create a Region3 that constantly moves and is shaped like a box? So there’s a Region3 for GhostItem.

You can use a function like this, to create a Region3 from a part:

function PartToRegion3(part)
    local PointA, PointB = part.CFrame * (0.5 * part.Size) , part.CFrame * (-0.5 * part.Size)
    local region = Region3.new(PointA, PointB)
    
    return region
end

You would need to create a new one every time the box moves.

I would honestly try using :GetTouchingParts() first, and see if that does you any good, as it isn’t as hard on performance. You may have to use this trick though, if GhostPart has CanCollide set to true.

:GetTouchingParts() did work! I didn’t even know that was a thing, thanks for the help :slight_smile:

1 Like