How to snap a CFrame to grid with offset / rotated model and rotated grid

Hey, in this game all the grids which can be built upon have a different rotation, I have already wrote the script which properly rotates my furniture items so that they match the grid, as shown below:

	RunService:BindToRenderStep("PlacementSession", 1, function()
		-- Away from character.
		local CFramePosition = Player.Character.PrimaryPart.CFrame
		CFramePosition *= BuildSystem.AwayFromPlayer

		-- Implement Height Fixes
		-- Changes the y value to be just above the grid.
		CFramePosition = PlacementSession.PlacementUtilities.adjustToGridTop(CFramePosition, self.TransparentModel.PrimaryPart, self.Grid)

		-- Implement Rotation
		CFramePosition = CFrame.new(CFramePosition.Position) * self.Grid.CFrame.Rotation
		CFramePosition *= CFrame.Angles(0,math.rad(self.Rotation),0) 	

		-- Needed:
		-- Snap to grid

		-- Render.
		self.TransparentModel:SetPrimaryPartCFrame(CFramePosition)
	end)

I now need a way to snap the CFrame to my grid, all of the solutions I can find work partially but after some rotations the CFrames position looses sync with my parts texture / grid so it looks broken.

Thanks!

2 Likes

Have you tried GridPlacer?: GridPlacer: Highly-featured module for part placement, rotation, and snapping to grid - Resources / Community Resources - Developer Forum | Roblox

3 Likes

Hi, I’m a little confused on how to implement it to my system / needs as I don’t currently use raycasting anywhere.

You can take the raycast code from a raycast based weapon, or I have some example code:

local UserInputService = game:GetService("UserInputService")

function InputBegan(input : InputObject, gameProcessed)
	--Mouse
	if input.UserInputType == Enum.UserInputType.MouseButton1 and not gameProcessed then
		
		--Find model or part in workspace
		local cam = workspace.CurrentCamera
		local ray = cam:ScreenPointToRay(input.Position.X, input.Position.Y, 0)
		
		local result = workspace:Raycast(ray.Origin, ray.Direction * 1000.0)
		
		if result ~= nil then
			local target = result.Instance

			--Your code here
		end
	end
end

UserInputService.InputBegan:Connect(InputBegan)
1 Like