Making my building system to build relative not only to the ground but also other blocks

You can write your topic however you want, but you need to answer these questions:

  1. What do you want to achieve? I want to make so that my building system works like build a boat and so that I can position blocks relative to one another and also allow me to build upwards

  2. What is the issue? The issue is that idk how I should make it so that I can build on they Y axis

  3. What solutions have you tried so far? Did you look for solutions on the Developer Hub?
    No solutions because I have no ideas.
    Yes, I have but I couldn’t find a system tat’s similar to my system.

After that, you should include more details if you have any. Try to make your topic as descriptive as possible, so that it’s easier for people to help you!

This is the code that generates the positions (the one that generates parts is just for visualization)

    for x = coords.minX, coords.maxX, gridsize do
	for z = coords.minZ, coords.maxZ, gridsize do
		position = Vector3.new(x,coords.maxY,z)
		table.insert(points, position)
	end
end

for i, pos in pairs(points) do
	position = Vector3.new(pos.X+gridsize/2,pos.Y,pos.Z+gridsize/2)
	table.insert(centers,position)
end
local newcenters = {}


for i, pos in pairs(centers) do
	if pos.X > coords["maxX"] or pos.X < coords.minX or pos.Z > coords.maxZ or pos.Z < coords.minZ then
		continue
	else
		table.insert(newcenters,pos)
	end
end

This is the code that compares the position of the cast to the position table (btw I used furniturepiece because I was working on a furniture placing system, but now I think a system like this would be better)

				for i, pos in pairs(centers) do
					if not closest then
						closest = pos
					elseif (cast.Position - pos).Magnitude < (cast.Position - closest).Magnitude then
						closest = pos
					end
				end
				furniturepiece.Position = Vector3.new(closest.X,closest.Y+furniturepiece.Size.Y/2,closest.Z)

This is my current building system (I actually haven’t started on the actual placing but right now I don’t know how to build upwards and put blocks on the side of others)
This system compares a cast of your mouse to each of these red parts (not the actual red parts but a table of positions) and then places the block on the closest point.

Should I use another placing mechanic or can I continue using this method?

Thanks for anything! :slight_smile:

The only problem I see is your unconventional way of getting the voxel. It should be much simpler than that:
Just round the Mouse.Hit position to the nearest voxel and offset it based on the Normal vector of the block that the mouse targets—no need to iterate through an entire table of points to get the closest one.

Here’s some example code from one of my old projects:

--Round the position to the nearest voxel; flr() is just math.floor
worldToVoxel = function(pos: Vector3): Vector3
	local v: Vector3 = pos / blockSize --blockSize is just the size of the voxels
	return Vector3.new(flr(v.X + .5), flr(v.Y + .5), flr(v.Z + .5))
end,
--this function is ran every frame; gets the voxel that the player is targeting at
local function mouseVoxel(): Vector3?
	local ray: RaycastResult? = cgl.mouse3D(worldRCP, m.range, true) --this function is basically just mouse.Hit but using raycasts instead
	if ray then

		--offset is just one-half of block size
		--m.normalDir is either -1 or 1, it controls the direction in which the position is offsetted by the normal.
		--If it's 1, it will position the voxel *next* to the targeted one (for building new blocks).
		--If it's -1, it will target the exact voxel (for deleting blocks).
		return cgl.worldToVoxel(ray.Position + ray.Normal * offset * m.normalDir)
	end
	return
end

Im sorry, I didn’t understand could you explain this a little bit easier?

The basic idea is that you can round vectors the same way you round numbers. Consider this example:

local function roundTo(num, to)
  return math.floor(num/to + .5) * to
end

--round to the nearest 10
print(roundTo(9, 10)) --> 10
print(roundTo(99, 10)) --> 100

--round to the nearest integer (just one)
print(roundTo(0.5001, 1)) --> 1
print(roundTo(0.4999, 1)) --> 0

--round to the nearest 25
print(roundTo(49, 25)) --> 50
print(roundTo(13, 25)) --> 25

And we just need to use this on Vector3s. That’s what the worldToVoxel() function in my last reply is for.
So, if each voxel is say 2 studs big and your mouse is at the position (1.5, 0, 3.2), you can round it to (2, 0, 4), and then shrink it back into unit vectors for easier use: (1, 0, 2).
(1.5, 0, 3.2) is the world position of your mouse.Hit, and (1, 0, 2) is the voxel position, aka. the block that the player is targeting.
But if you want to select the voxel right next to the block (as to build like in Minecraft), you will have to offset it based on the Normal of the block that’s selected.

Okay, so using:

--Round the position to the nearest voxel; flr() is just math.floor
worldToVoxel = function(pos: Vector3): Vector3
	local v: Vector3 = pos / blockSize --blockSize is just the size of the voxels
	return Vector3.new(flr(v.X + .5), flr(v.Y + .5), flr(v.Z + .5))
end,

and

--this function is ran every frame; gets the voxel that the player is targeting at
local function mouseVoxel(): Vector3?
	local ray: RaycastResult? = cgl.mouse3D(worldRCP, m.range, true) --this function is basically just mouse.Hit but using raycasts instead
	if ray then

		--offset is just one-half of block size
		--m.normalDir is either -1 or 1, it controls the direction in which the position is offsetted by the normal.
		--If it's 1, it will position the voxel *next* to the targeted one (for building new blocks).
		--If it's -1, it will target the exact voxel (for deleting blocks).
		return cgl.worldToVoxel(ray.Position + ray.Normal * offset * m.normalDir)
	end
	return
end

This will return me the position at wich the block has to be?
Also, would this work with stuff bigger than the block like instead of a 1x1x1 cube (actual size 4x4x4) if I had a idk 4x6x4 part? For example if I had a machine (mesh) and then a invisble bounding box where I could place other blocks?
Oh and also does this like work with my grid or do I have to add something to the code?
Sorry for all these questions, your code is way better and more complex than anything I’ve written before, idek what this does:

 : Vector3? 

Well but that doesn’t matter I think, thanks for the explanation btw!

Idk if I did something wrong or if I am just really stupid but this didn’t work