How do i add snapping, rotating, and movement to my placing system

I’m not sure at all how to do the snapping and no tutorials have helped so i would appreciate an example or explanation

this is my current code and i’ve only gotten it to place and move i attempted rotation but got lost

local RunService = game:GetService("RunService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local UserInputService = game:GetService("UserInputService")
local CollectionService = game:GetService("CollectionService")

local Preview = nil
local CurrentBuild = ReplicatedStorage["Build Items"]["Wooden Wall"]

local function preparePreview(preview: Model)
	for _, part in preview:GetChildren() do
		if part:IsA("BasePart") then
			part.CanCollide = false
			part.Transparency = 0.5
		end
	end
end

Preview = CurrentBuild:Clone()
Preview.Parent = workspace
preparePreview(Preview)

--[[Player Variables]]
local player = game.Players.LocalPlayer
local mouse = player:GetMouse()
local cc = workspace.CurrentCamera

local raycastParams = RaycastParams.new()
raycastParams.FilterDescendantsInstances = {player.Character, Preview}
raycastParams.FilterType = Enum.RaycastFilterType.Exclude

local function GetMouseLocation()
	local MouseLocation = UserInputService:GetMouseLocation()
	local UnitRay = cc:ViewportPointToRay(MouseLocation.X, MouseLocation.Y)
	local cast = workspace:Raycast(UnitRay.Origin, UnitRay.Direction * 1000, raycastParams)
	
	if cast and CurrentBuild ~= nil then
		local hitPosition = cast.Position

		local hitNormal = cast.Normal
		local lookAtPosition = hitPosition + hitNormal
		local orientation = CFrame.lookAt(hitPosition, lookAtPosition, hitNormal)
		Preview:PivotTo(orientation)
		CurrentBuild:PivotTo(Preview:GetPivot())
	else
		return
	end
end

local RotationAmount = 0

UserInputService.InputBegan:Connect(function(input, gpe)
	if gpe then return end
	
	if input.UserInputType == Enum.UserInputType.MouseButton1 then
		Preview = nil
		ReplicatedStorage.Communication.Placement:FireServer(CurrentBuild)
	end
end)

local Running

Running = RunService.RenderStepped:Connect(function()
	if Preview == nil then
		Running:Disconnect()
	else
		GetMouseLocation()
	end
end)
1 Like

For the snapping part, you only need one small modification on line 37:

local hitPosition = cast.Position - Vector3.new(cast.Position.X % 1, cast.Position.Y % 1, cast.Position.Z % 1)

to alter the size of the snapping grid, simply change the % 1 to % yourDesiredGridSize


The percent sign is called the modulo operator. It takes a number like in your case cast.Position.X divides it by your grid size (1) and returns the remainder.

Here are some examples:

10 % 2 = 0
1 % 2 = 1
16 % 5 = 1
3.42 % 1 = 0.42
100 % 25 = 0
10.87 % 3 = 1.87

thanks still looks complicated to me but i’ll try to understand it

also i assumed this was using raycastparams i only want to include parts with a tag “Grid” but dont know if that possible or not to use tags or if i would have to give a path for every grid instead