Annoying jittering with snap to grid for building system

I’ve been working on a simple building system inspired by WTRB and just the stamper tool in general however for some reason when rounding the part’s position it keeps jittering in and out of the place where the mouse is as if it can’t decide where to go

I’ve tried looking up solutions to this but all i could find were different ways to round it none of which actually fixed anything

this is the code that gets and rounds the position of the block

function roundToGrid(value)
	return math.floor(value / 4 + 0.5) * 4
end

local gridSize = 4

while task.wait() do
	if ghostBlock and equipped then
		local params = RaycastParams.new()
		params.FilterType = Enum.RaycastFilterType.Exclude
		params.FilterDescendantsInstances = {workspace.Players,ghostBlock}
		local ray = workspace:Raycast(cam.CFrame.Position,mouse.Hit.LookVector*1000,params)
		if ray and ray.Instance then
			local mPos = ray.Position
			local blockCF = CFrame.new(
				roundToGrid(mPos.X),
				roundToGrid(mPos.Y),
				roundToGrid(mPos.Z)
			)
			blockCFrame = blockCF
			print("CF: ",blockCFrame)
			ghostBlock:PivotTo(blockCFrame*blockRot)
			if game:GetService("RunService"):IsStudio() then
				game.JointsService:SetJoinAfterMoveInstance(ghostBlock)
				game.JointsService:SetJoinAfterMoveTarget(mouse.Target)
				game.JointsService:ShowPermissibleJoints()
			end
		end
	end
end

i really have no clue what I’m doing wrong as I’ve made building systems before yet when I’ve tried taking code from them to fix this issue nothing changes

ok so the problem is ray.Position is right on the surface you’re pointing at, and with 4 stud blocks on a 4 stud grid that surface is always right on the edge between 2 grid spots. so tiny float stuff (like 1.9999 vs 2.0001) makes your rounding pick a different spot every frame = jitter

two changes fix it. first push the point out half a block along the surface normal so it’s inside the spot you actually wanna place in:

local mPos = ray.Position + ray.Normal * (gridSize / 2)

then snap to the middle of the grid cell instead of rounding to the nearest multiple of 4. otherwise the baseplate (top at y=0) puts you right back on the edge and it still flickers:

local gridSize = 4

function roundToGrid(value)
	return math.floor(value / gridSize) * gridSize + gridSize / 2
end

blocks will sit flush on the baseplate and on each other’s faces now. if your ground isn’t at a multiple of 4 just shift it so it is

2 Likes

That seems to have worked perfectly, thank you

1 Like