How can I make a part move from the mouse with a 1 stud grid?

Hello everyone, so this is my code so far that moves a part to where the mouse is pointing and it works well:

mouse.Move:connect(function()
	
	mouse.TargetFilter = movePart
	
	if (mouse.Target) then
		
		local target = mouse.Target
				
		local X = target.Position.X
		local Y = target.Position.Y
		local Z = target.Position.Z
		
		local rotX = target.Orientation.X
		
		local rotY = target.Orientation.Y
		local rotZ = target.Orientation.Z
		
		local Angles = CFrame.Angles(math.rad(rotX), math.rad(rotY), math.rad(rotZ))
		
		local newPos = CFrame.new((mouse.Hit.X),(mouse.Hit.Y),(mouse.Hit.Z)) * Angles
		
		
		movePart.CFrame = newPos * CFrame.new(0,0,0.5)
		

	end
	
end)

But when I try to move it by a 1 stud grid it doesn’t work well, and when the target is at an angle the part’s position wobbles along the target. So I need to find a way for the part to move where the mouse is pointing but in a 1 stud grid/at 1 stud and here is where I need help. Thank you.

2 Likes

See if something like that works

Thanks, I just tried it, but the part i’m moving with the mouse still wobbles when the target is at an angle. That seems to be the only problem.

you can round each axis to the nearest multiple of 1.

local newX = math.floor(X + 0.5)

You can also round to the nearest multiple of N (if you want to move within cells that are bigger)

local newX = math.floor(X / N + 0.5) * N

Putting this together in different ways can achieve different things.

local function snap(v3, w, h, l)
	return Vector3.new(
		math.floor(v3.X / w + 0.5) * w,
		math.floor(v3.Y / h + 0.5) * h,
		math.floor(v3.Z / l + 0.5) * l
	)
end
local newPos = snap(part.Position, 1,1,1)

This for example can help you snap parts to different cells based on the parts dimensions, or specified dimensions.

Thanks, but I have this and it doesn’t seem to work. The part just goes to where the mouse is pointing in the center of the target but doesn’t move by any stud and is stuck there. This is my code:

mouse.Move:connect(function()
	
	mouse.TargetFilter = movePart
	
	if (mouse.Target) then
		
	--	wait(3)
		
		local target = mouse.Target
				
		local X = target.Position.X
		local Y = target.Position.Y
		local Z = target.Position.Z
		
		local rotX = target.Orientation.X
		
		local rotY = target.Orientation.Y
		local rotZ = target.Orientation.Z
		
		local Angles = CFrame.Angles(math.rad(rotX), math.rad(rotY), math.rad(rotZ))
		
		local val = 0.5
		
		local newPos = snap(target.Position, 1,1,1)

		
		movePart.CFrame = CFrame.new(newPos) * Angles --* CFrame.new(0,0,0.5)
		

	end
	
end)
1 Like

sorry, in this case you would snap the mouse hit coordinates, I didn’t specify.

local newPos = snap(mouse.Hit.Position, 1,1,1) --returns a vector3

It might also be ideal to dispose of the Y axis and use a “currentHeight” value or something, at least until you need surface normals and such.

2 Likes

Thank you, but the problem is that the part is wobbling in and out of the wall when it moves with the mouse and that is not ideal for my situation. Do you know how I could fix this and just have smooth movement along the wall?

1 Like

It probably has something to do with orientation/angles being used together or the part filter, but im not quite sure.

You could place this at the top and provide a rotation setting the player can change to update it.

local angles = CFrame.Angles(math.rad(0), math.rad(0), math.rad(0))

and then do something like.

local movePart = nil
local angles = CFrame.Angles(math.rad(0), math.rad(0), math.rad(0))

local function snap(v3, w, h, l)
	return Vector3.new(
		math.floor(v3.X / w + 0.5) * w,
		math.floor(v3.Y / h + 0.5) * h,
		math.floor(v3.Z / l + 0.5) * l
	)
end

function setRotation(x,y,z)
    angles = CFrame.Angles(math.rad(x), math.rad(y), math.rad(z))
end

function handleMove()
    mouse.TargetFilter = movePart
	
	if (mouse.Target) then
        local newPos = snap(mouse.Hit.Position, 1,1,1)
        movePart.CFrame = CFrame.new(newPos.X, newPos.Y, newPos.Z) * angles
    end
end
1 Like

Thanks, I tried that but unfortunately the part just doesn’t want to move evenly/smoothly across the surface when you snap it to the grid. :confused: I don’t know why.

1 Like

https://gyazo.com/fb8bfc4a3893b2695be9431596814d80

This seems to work for me while using the InputChanged event and the rotation works as well.
Its all smooth, so maybe your original code had a design flaw somewhere

LOCALSCRIPT EXAMPLE

local uis = game:GetService("UserInputService")
local ps = game:GetService("Players")
local player = ps.LocalPlayer
local mouse = player:GetMouse()
local angles = CFrame.new(0,0,0)
local cellPosition = Vector3.new(0,0,0)
local currentHeight = 0

local selectedPart = Instance.new("Part")
selectedPart.Size = Vector3.new(1,1,1)
selectedPart.Color = Color3.fromRGB(255, 0, 0)
selectedPart.Anchored = true
selectedPart.Parent = workspace
mouse.TargetFilter = selectedPart




local function snap(v3, w, h, l)
	return Vector3.new(
		math.floor(v3.X / w + 0.5) * w,
		math.floor(v3.Y / h + 0.5) * h,
		math.floor(v3.Z / l + 0.5) * l
	)
end

function rotate(x,y,z)
	angles = CFrame.Angles(math.rad(x), math.rad(y), math.rad(z))
end



uis.InputChanged:Connect(function(i,g)
	if(i.UserInputType == Enum.UserInputType.MouseMovement)then
		if(mouse.Target)then
			print(mouse.Target.Name)
			cellPosition = snap(mouse.Hit.Position, 1,1,1)
			print(cellPosition)
			currentHeight = cellPosition.Y + selectedPart.Size.Y/2
			selectedPart.CFrame = CFrame.new(cellPosition.X, currentHeight, cellPosition.Z) * angles
		end
	end
end)

https://gyazo.com/b5a481a83c13300a792785f078f5edf7

but you’ll see that its naive for the side of surfaces (especially when placed on more complex meshes), you’ll need to look into how to get surface normals, and then use those surface normals to offset your selected part.

If you dont want to use surface normals, then you’ll have to make sure your map (or build area) is built within the same 1x1x1 cells in mind.

1 Like

Thank you for the code. But does it work on walls that are at an angle (not 90 degrees)?

1 Like

youre welcome, the code is mainly an example, hopefully you find your exact issue by referencing it.

and as for the question, yes you can get placement to work at more complex angles but it’ll require more math than just surface Normals. (and more work than simply lining up the map with your 1x1x1 cells)

you’ll need some trigonometry concepts I imagine in combination with surface normals but that’s probably out of my league lol…

but it can probably be simplified by just letting your players set the parts rotation in specific increments (lets say 15 degrees? if the smallest angle for slopes is 15 degrees), that way the players can line up the parts to the different slopes by themselves.

this could be impractical in some situations though, especially if you dont want issues with noclipping parts.

1 Like

Yes, thank you. Do you think that if I change movePart’s transparency to 1 when it is not in a certain range and change it to 0 when it is is that I can achieve a similar effect?

1 Like