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.
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)
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?
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
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. I don’t know why.
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)
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.
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.
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?