Placement system SnapToGrid off by 0.5 studs for certain objects

I am working on a placement system that has been working great overall, however, the snapping system only works on intended on some objects.

I am trying to make objects snap every 1 stud. It does snap but it is sometimes off by 0.5 studs relative to the plot.

image

This is how it appears on the grid, another objects I have sits perfectly on each stud while this wall has been giving me issues.

This is the code for snapping:

function PlacementValidator.SnapToGrid(pos, objectSize, plotPos)
	local GRID_SIZE = 1
	
	return Vector3.new(
		(pos.X // GRID_SIZE),
		plotPos.Y + 0.5,
		(pos.Z // GRID_SIZE)
	)
end

which is then used here:

local cast = castMouse() --raycast function
	if cast and cast.Position then
		local size = self.Preview:GetExtentsSize()
		local plotPos = self.Plot.PrimaryPart:GetPivot()

		local snappedPosition = PlacementValidators.SnapToGrid(cast.Position, size, plotPos)

		local cf = CFrame.new(snappedPosition) * CFrame.Angles(0, self.Rotation, 0) 
		
		self.Preview:PivotTo(cf)

I have seen other posts on snapping but I could not figure out how to implement in my system, it seems like such a simple fix but I am missing something. Thanks for any help!

Edit: I also see that this only happens for sizes that are odd numbers. When a size is an even number like 2 or 8 it works fine but 1 and 5 and such are offset by 0.5.

2 Likes

Try using math.floor on the SnapToGrid function:

function PlacementValidator.SnapToGrid(pos, objectSize, plotPos)
    local GRID_SIZE = 1
    
    local snappedX = math.floor(pos.X / GRID_SIZE + 0.5) * GRID_SIZE
    local snappedY = plotPos.Y + 0.5
    local snappedZ = math.floor(pos.Z / GRID_SIZE + 0.5) * GRID_SIZE
    
    return Vector3.new(
        snappedX,
        snappedY,
        snappedZ
    )
end
2 Likes

Still gives me the same issues cause I used the double divide symbol pos.x // GRID_SIZE to do math.floor (I’ve heard that works as an option?)

Maybe try factoring in objectSize

function PlacementValidator.SnapToGrid(pos, objectSize, plotPos)
	local GRID_SIZE = 1
	
	local halfGridSize = GRID_SIZE / 2
	local halfObjectSizeX = objectSize.X / 2
	local halfObjectSizeZ = objectSize.Z / 2

	local snappedX = (pos.X - halfObjectSizeX + halfGridSize) // GRID_SIZE * GRID_SIZE + halfObjectSizeX
	local snappedZ = (pos.Z - halfObjectSizeZ + halfGridSize) // GRID_SIZE * GRID_SIZE + halfObjectSizeZ
	
	return Vector3.new(
		snappedX,
		plotPos.Y + 0.5,
		snappedZ
	)
end
2 Likes

It’s close, on one orientation it works but when I rotate it 90 degrees in game then it becomes offset again.

2 Likes

Found a workaround for this method. If the object has an odd number size on let’s say the x axis, then you just edit the pivot on the actual model so that it is not in the middle of an odd number (which caused it to be offset by 0.5; if the pivot is in the middle of 1 stud then it will snap to the middle of that 1 stud which is 0.5)

Hopefully this makes sense its a little hard to explain lol, just edit the pivot

2 Likes