Snap to grid even if out of boundary

How would I make the object snap even if the cursor is not on the grid?

For example, if you move your cursor, and if its out of the grid, I’d still like it to snap the object.

2 Likes

Show code

1 Like
RunService.Heartbeat:Connect(function(dt)
	if mouse.Target ==  nil then return end
	
	if mouse.Target.Parent.Parent.Name == "gridParts" then -- checks if its a grid part
		local pos = mouse.Target.CFrame
		
		TweenService:Create(selectionpart.PrimaryPart,TweenInfo.new(0.4,Enum.EasingStyle.Quad),
		{CFrame = pos * CFrame.Angles(0, math.rad(rotation), 0)}
		):Play()
	end
end)
2 Likes

In addition to checking if the mouse is over a “gridParts” you should also add an elseif for the case where the mouse is outside the boundary.

From there, just use math.clamp to get the nearest position inside the grid and tween to that position

1 Like

Thank you, how exactly would I use math.clamp to achieve that?

2 Likes

Edited your code a bit, commented the relevant parts too. Lmk if you have any other questions

--you will need to know the grid size in worldspace position
local gridsizeX = {0, 10}
local gridsizeZ = {0, 10}

RunService.Heartbeat:Connect(function(dt)
	if mouse.Target ==  nil then return end
	
	if mouse.Target.Parent.Parent.Name == "gridParts" then -- checks if its a grid part
		local pos = mouse.Target.CFrame
		
		TweenService:Create(selectionpart.PrimaryPart,TweenInfo.new(0.4,Enum.EasingStyle.Quad),
		{CFrame = pos * CFrame.Angles(0, math.rad(rotation), 0)}
		):Play()
	else
		--SECOND PART
		local pos = mouse.Target.CFrame

		--clamp the X/Z positions here and add the angle directly
		local cframeClampedPosition = CFrame.new(
			math.clamp(pos.X, gridsizeX[1], gridsizeX[2]),
			pos.Y,
			math.clamp(pos.Z, gridsizeZ[1], gridsizeZ[2])
		) * CFrame.Angles(0, math.rad(rotation), 0)

		TweenService:Create(selectionpart.PrimaryPart,TweenInfo.new(0.4,Enum.EasingStyle.Quad),
		{CFrame = cframeClampedPosition}
		):Play()
	end
end)
1 Like
local gridsizeX = {0, 10}
local gridsizeZ = {0, 10}

Thank you, would these variables be both the X/Z position? For example:

local gridsizeX = {workspace.plot.Position.X, workspace.plot.Position.X}
local gridsizeZ = {workspace.plot.Position.Z, workspace.plot.Position.Z}
2 Likes
local plot = workspace.plot
local plotSize = plot.Size

local gridsizeX = {
    plot.Position.X - plotSize.X / 2,
    plot.Position.X + plotSize.X / 2
}

local gridsizeZ = {
    plot.Position.Z - plotSize.Z / 2,
    plot.Position.Z + plotSize.Z / 2
}
2 Likes

It’s the position points like this image

1 Like

I see, I tried with the updated code however doesnt seem to function properly

1 Like

Yeah because the clamped positions are going to 0,10 in worldspace position. You need to find the actual bounds on your grid where the points are.

@bg9 provided good code to find those points

local plot = workspace.plot
local plotSize = plot.Size

local gridsizeX = {
    plot.Position.X - plotSize.X / 2,
    plot.Position.X + plotSize.X / 2
}

local gridsizeZ = {
    plot.Position.Z - plotSize.Z / 2,
    plot.Position.Z + plotSize.Z / 2
}

these positions you mean? I already have them as those not 0,10

1 Like

Is your plot the black square in the video?

Mhm correct, yes thats the plot workspace.plot

1 Like

It might be rotated weird, like the XYZ might be flipped on it’s side so the orientation isn’t correct. Try playing around with the values until you find how it’s orientated. Or print out the gridsizeX and gridsizeZ to check if the positions are correct

Try this:

--you will need to know the grid size in worldspace position
local plot = workspace.plot
local plotSize = plot.Size

local gridsizeX = {
    plot.Position.X - plotSize.X / 2,
    plot.Position.X + plotSize.X / 2
}

local gridsizeZ = {
    plot.Position.Z - plotSize.Z / 2,
    plot.Position.Z + plotSize.Z / 2
}

RunService.Heartbeat:Connect(function(dt)
	if mouse.Target ==  nil then return end
	
	if mouse.Target.Parent.Parent.Name == "gridParts" then -- checks if its a grid part
		local pos = mouse.Hit
		
		TweenService:Create(selectionpart.PrimaryPart,TweenInfo.new(0.4,Enum.EasingStyle.Quad),
		{CFrame = pos * CFrame.Angles(0, math.rad(rotation), 0)}
		):Play()
	else
		--SECOND PART
		local pos = mouse.Hit

		--clamp the X/Z positions here and add the angle directly
		local cframeClampedPosition = CFrame.new(
			math.clamp(pos.X, gridsizeX[1], gridsizeX[2]),
			pos.Y,
			math.clamp(pos.Z, gridsizeZ[1], gridsizeZ[2])
		) * CFrame.Angles(0, math.rad(rotation), 0)

		TweenService:Create(selectionpart.PrimaryPart,TweenInfo.new(0.4,Enum.EasingStyle.Quad),
		{CFrame = cframeClampedPosition}
		):Play()
	end
end)

thats literally my code bro -_-

1 Like

The orientation is 0,0,0 and the values are also correct, rotating doesn’t do anything

What happens when you do this?

This is the result, look above