How can I add snap-to-grid to my placement system

I am working on a placement system. The orientation of the placeable model is determined by what the mouse is being hovered over.

This is a snippet of the code that’s needed for this post.

run_service.Heartbeat:Connect(function()
		local ray = client_modules.libraries.mouse.raycast(ray_params)

		if not (ray and ray.Position and ray.Instance) then
			return
		end

		local ray_position = ray.Position
		local instance_orientation = (ray.Instance.CFrame - ray.Instance.CFrame.Position)

		local normal = ray.Normal * self.model:GetExtentsSize() / 2
		
		local cframe = CFrame.new(ray_position + normal) * instance_orientation

		self.model:PivotTo(cframe)
	end)

Here are demonstrations that the orientation of the model can change depending on the surface.

image
image

My question is how can I add a snap-to-grid system that ignores the axis of whatever part the block is on? For example, if you are placing something on the ground, the snap to grid only affects X and Z, and not Y. If you are placing something on a 45-degree rotated part, that would be a little more complicated.

Would I use :ToObjectSpace() or something similar?

Thank you for your time.

I personally would use the perpendicular vectors of the surface normal, find the relative X and Z offset needed to reach the mouse hit from the origin of the grid. I’d then round those offset values to the grid increment and then add those offsets to the origin to find the new position. Hopefully this makes sense, but do note this method breaks down with meshs and terrain as they can have more complex geometry, where finding or deciding an origin is hard or impossible.

1 Like