How to make a block placement system that aligns to a part grid?

Hey,

I’ve made building systems before where parts are snapped to a grid, which is fine and all, but I want to be able to align the grid with another part that isn’t centered, since my game has moving parts that need to be built on top of.

That’s about it, I’m just looking for some equation/way to snap a part. Think Minecraft building, except it works on parts that aren’t aligned with the horizon (rotated). So just snapping to surfaces.

Thanks.

Try using modulus (% operator) or floor division (// operator)

I actually found a solution.

I modified my script to just be anchored, however it has the same logic. All you would have to do is set the result to new, NOT - CFrame.new(new.Position)

function SnapToGridWithOffset(pos: Vector3, offset: Vector3)
	return Vector3.new(
		math.round(pos.X / GRID_SIZE) * GRID_SIZE,
		math.round(pos.Y / GRID_SIZE) * GRID_SIZE,
		math.round(pos.Z / GRID_SIZE) * GRID_SIZE
	) + offset
end

RunService.Heartbeat:Connect(function()
	Template = AllBuilds[BuildSelection]
	
	local result = nil

	if Mouse.Target and Mouse.Target:HasTag("BuildableSurface") then
		local Distance = (Mouse.Hit.Position - Player.Character.PrimaryPart.Position).Magnitude
		
		if Distance <= 30 then
			Target = Mouse.Target
		else
			Target = nil
		end
	else
		Target = nil
	end

	local Offset = Vector3.new(0, -CurrentPreview.PrimaryPart.Size.Y, 0)

	if Target then
		local distance = Target.CFrame:ToObjectSpace(Mouse.Hit).Position

		local second = Page(distance)

		local new = Target.CFrame * CFrame.new(SnapToGridWithOffset(second, Offset)) * CFrame.new(Vector3.new(0, 6, 0))

		local checkeddistance = (Target.Position - new.Position)

		if math.abs(checkeddistance.Magnitude) >= GRID_SIZE - 1 then
			result = CFrame.new(new.Position)
            -- to properly set rotation, replace the above line with; result = new
		end
	end

	if result then
		CurrentPreview.Parent = workspace.CurrentCamera

		CurrentPreview:PivotTo(CurrentPreview.PrimaryPart.CFrame:Lerp(result * Rotation, 0.5))
	else
		CurrentPreview.Parent = nil
	end
	
	CF = result or CFrame.new()
end)

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.