# How to snap a part to grid

I am making a game where you can build. Now one problem.

I want to make a grid thingy where the part snaps to a grid. I tried using

`CFrame.new(position.X - position.X%3, position.Y - position.Y%3, position.Z - position.Z%3).Position`
I also tried math.floor(X / 3) * 3 but it gives the same result

If i want to build up, then place a part on the left side or right side then only one side works, if i try placing the block it goes inside of the block, but not on the other side.

Is there any other method? How do i fix this?
some other info:
The part is a 3x3x3 and the snap value is 3, so it will snap every 3 studs
The baseplate is one single block, thereâ€™s no multiple blocks simulating a grid.
I want a snapping similar to Build A Hideout And Sword Fightâ€™s

1 Like

The math.floor() way should have worked. Can you show the exact code you used? Also try using math.round instead of floor, it should feel more natural.

that is the whole code, math.floor one is the exact same as the other (x - x%3)

math.floor does not give any better results

EDIT: By whole code I mean thatâ€™s the only function I used, its literally Part.Position = and the formula

I need all your code to understand the input position youâ€™re using.

``````local module = {}

module.SelectedBlock = "Brick"

function module.Snap(position, ins, Object)
if Object:IsA("BasePart") then
--if ins.Instance.Name == "BasePlot" then
--	return Vector3.new(position.X - position.X%3, position.Y + Object.Size.Y/2, position.Z-position.Z%3)
--else
--	return ins.Instance.CFrame:PointToWorldSpace(ins.Normal * 3)
--end
return CFrame.new(position.X - position.X%3, position.Y - position.Y%3 + Object.Size.Y, position.Z - position.Z%3).Position
else
--if ins.Instance.Name == "BasePlot" then
--	return Vector3.new(position.X - position.X%3, position.Y + Object:GetExtentsSize().Y / 2, position.Z-position.Z%3)
--else
--	return ins.Instance.CFrame:PointToWorldSpace(ins.Normal * 3)
--end
return CFrame.new(position.X - position.X%3 + 1, position.Y - position.Y%3 + Object.PrimaryPart.Size.Y, position.Z - position.Z%3 + 1).Position
end
end
function module:placeBlock(x : string, position : Vector3, ins : RaycastResult, ori : Vector3)
local fObject = script.Parent.Parent.Items:FindFirstChild(x)
if not fObject then return "Failed" end
script.Parent.Parent.Construct:InvokeServer({
TypeOfCall = "Place",
Object = fObject.Name,
Position = module.Snap(position, ins, fObject),
Orientation = ori
})
end
function module:removeBlock(block : BasePart)
script.Parent.Parent.Construct:InvokeServer({TypeOfCall = "Remove", Object = block})
end

return module
``````

The code in â€“ is the one that works, but its the most non-effecient thing

You seem to have two different positions going into Snap, â€śpositionâ€ť and the raycast resultâ€™s Position (ins.Position), did you mean to use ins.Position?

No, the code i put is fully working;

The commented code is the method that works, but I said its bad, since it uses 2 different methods into one

Sorry Im a bit late but If you still want some help with this here is a bit of code I just made for my building game. Even if ya donâ€™t need it Ima still post it for those who might.

``````function Snap(HitPosition:Vector3,SnapAmount:number,BlockSize:Vector3,HitNormal:Vector3)
local NewPos = HitPosition+(HitNormal*(BlockSize/2)) -- Gets the new position of a block
local X = math.floor((NewPos.X+(SnapAmount/2))/SnapAmount)*SnapAmount -- Gets the position snapped to the snap amount on the x Axis
local Y = math.floor((NewPos.Y+(SnapAmount/2))/SnapAmount)*SnapAmount -- Gets the position snapped to the snap amount on the y Axis
local Z = math.floor((NewPos.Z+(SnapAmount/2))/SnapAmount)*SnapAmount -- Gets the position snapped to the snap amount on the z Axis
local NewBlockPos = Vector3.new(math.round(X*1000)/1000,math.round(Y*1000)/1000,math.round(Z*1000)/1000) -- Removes floating point imprecision.
return NewBlockPos
end
``````

Also Here is a version for purely snapping to a Position without calculating a blockâ€™s new position

``````function Snap(Position:Vector3,SnapAmount:number)
local X = math.floor((Position.X+(SnapAmount/2))/SnapAmount)*SnapAmount -- Gets the position snapped to the snap amount on the x Axis
local Y = math.floor((Position.Y+(SnapAmount/2))/SnapAmount)*SnapAmount -- Gets the position snapped to the snap amount on the y Axis
local Z = math.floor((Position.Z+(SnapAmount/2))/SnapAmount)*SnapAmount -- Gets the position snapped to the snap amount on the z Axis
local NewBlockPos = Vector3.new(math.round(X*1000)/1000,math.round(Y*1000)/1000,math.round(Z*1000)/1000) -- Removes floating point imprecision.
return NewBlockPos
end
``````

Note: The `math.round(Number*1000)/1000` bit is to remove any floating point imprecision, it is not 100% needed if you donâ€™t want it. Also 1000 can be made bigger to allow a higher decimal count.

Also the reason your first attempt didnâ€™t work is most likely because math.floor will cause the position to be slightly offset which is what the `+(SnapAmount/2)` does is to eliminate that offset.

Another Alternative to `math.floor((Position.X(SnapAmount/2))/SnapAmount)*SnapAmount` is
`math.round(Position.X/SnapAmount)*SnapAmount` but I dont recomment it because it breaks a bit in some parts of the world.

Hopefully this actually works and I didnâ€™t make a mistake while editing it.