I want to try creating a placement system from scratch. Although the mouse position and hit is easily accessible, how can I snap it onto a grid based on an editable stud increment, on all 3 axis? If you give formulas or sample code, please explain so I can understand it.
You can do this through a simple function.
function Round(x: number, y: number, z: number, grid: number)
return Vector3.new(
math.floor(x / (grid) + 0.5) * grid,
math.floor(y / (grid) + 0.5) * grid,
math.floor(z / (grid) + 0.5) * grid
)
end
The expression math.floor(x / grid + 0.5)
is used to round x
to the nearest multiple of grid
.
x / grid
: Divides the x
coordinate by grid
to normalize it to the grid system.
math.floor()
, it just rounds the number.
Multiplying by grid
: After rounding, we multiply the result by grid
to bring it back into the original scale, effectively snapping the coordinate to the nearest grid multiple.
Edit: @EtNowis 's explanation is a lot better!
suppose our grid is 1 stud in size,
we can use newX = math.floor(pos.X)
to snap its center to a grid intersection. (do the same for all axis)
notice our block sizeX = 1, so its center is at 0.5, if we want to keep the block at the space rather than at the grid intersection, we need to offset by 0.5
newX = math.floor(pos.X) + 0.5
the same is actually true for all odd sizeX
if however our sizeX is even, then we don’t have to offset it because its center should sit right at the grid line.
newX = math.floor(pos.X)
combine both cases, we can do
newX = math.floor(pos.X) + ( math.floor(size.X) % 2 == 0 ? 0 : 0.5 )
or use if
for easier understanding.
What if the grid is not 1 stud in size? Suppose the grid is 2 stud, now a 2x2x2 block equals 1 grid in length, and a 4x4x4 block is 2 grid in length. so we see that we can simply divide by gridSize
to get the grid coordinate
newX_in_grid = math.floor(pos.X / gridSize) + ( math.floor(size.X / gridSize) % 2 == 0 ? 0 : 0.5 )
then we multiply by gridSize again to convert into world coordinate
newX = newX_in_grid * gridSize
You both explained it very well! Thank you for your responses!