I’m making a system where you can move, rotate or scale objects but I have a slight problem
local player = game.Players.LocalPlayer
local playerGui = player:WaitForChild("PlayerGui")
local part = workspace:WaitForChild("MovablePart")
local handles = Instance.new("Handles")
handles.Parent = playerGui
handles.Adornee = part
handles.Style = Enum.HandlesStyle.Movement
local grid = 0.2
local faceActions = {
[Enum.NormalId.Front] = function(value) return value * -1 end,
[Enum.NormalId.Back] = function(value) return value end,
[Enum.NormalId.Left] = function(value) return value * -1 end,
[Enum.NormalId.Right] = function(value) return value end,
[Enum.NormalId.Top] = function(value) return value end,
[Enum.NormalId.Bottom] = function(value) return value * -1 end
}
handles.MouseDrag:Connect(function(face, distance)
local movedistance = distance * grid
local newPos = part.Position
if face == Enum.NormalId.Front or face == Enum.NormalId.Back then
local moveDirection = part.CFrame:vectorToWorldSpace(Vector3.new(0, 0, faceActions[face](movedistance)))
newPos = newPos + moveDirection
elseif face == Enum.NormalId.Left or face == Enum.NormalId.Right then
local moveDirection = part.CFrame:vectorToWorldSpace(Vector3.new(faceActions[face](movedistance), 0, 0))
newPos = newPos + moveDirection
elseif face == Enum.NormalId.Top or face == Enum.NormalId.Bottom then
local moveDirection = part.CFrame:vectorToWorldSpace(Vector3.new(0, faceActions[face](movedistance), 0))
newPos = newPos + moveDirection
end
part.Position = newPos
end)
When I move with the cursor, it sometimes “overshoots” when dragging with the Handle.
What am I doing wrong here?
i think vectorToWorldSpace takes into account the scale of the Part
you can check that if your scaled up your part, and then do the drag, it will overshoot now?
-- we rotate to the direction first, then scale by the move distance
local moveDirection = part.CFrame:vectorToWorldSpace(Vector3.new(0, 0, faceActions[face](1))).Unit * movedistance
newPos += moveDirection
we can use Vector3.FromNormalId to simplify things
local player = game.Players.LocalPlayer
local playerGui = player:WaitForChild("PlayerGui")
local part = workspace:WaitForChild("MovablePart")
local handles = Instance.new("Handles")
handles.Parent = playerGui
handles.Adornee = part
handles.Style = Enum.HandlesStyle.Movement
local grid = 0.2
handles.MouseDrag:Connect(function(face, distance)
local movedistance = distance * grid
local moveDirection = part.CFrame:vectorToWorldSpace(Vector3.FromNormalId(face)).Unit * movedistance
part.Position += moveDirection
end)
I think I might know why it’s overshooting:
Since we are just using the distance, there will be multiple distance, which would be like applying the same distance variable multiple times, which causes the overshooting:
Secondly, this is applying on the position, when it is supposed to apply on the part’s last position
I realized the issue, thanks.
I managed to fix the issue. Here is the solution for anyone wondering
local player = game.Players.LocalPlayer
local playerGui = player:WaitForChild("PlayerGui")
local part = workspace:WaitForChild("MovablePart")
local handles = Instance.new("Handles")
handles.Parent = playerGui
handles.Adornee = part
handles.Style = Enum.HandlesStyle.Movement
local faceActions = {
[Enum.NormalId.Front] = function(value) return value * -1 end,
[Enum.NormalId.Back] = function(value) return value end,
[Enum.NormalId.Left] = function(value) return value * -1 end,
[Enum.NormalId.Right] = function(value) return value end,
[Enum.NormalId.Top] = function(value) return value end,
[Enum.NormalId.Bottom] = function(value) return value * -1 end
}
local lastPosition = nil
local lastDistance = nil
local grid = 1
handles.MouseButton1Down:Connect(function()
lastPosition = Vector3.new(part.Position.X, part.Position.Y, part.Position.Z) -- Store the part's position as a reference
end)
handles.MouseDrag:Connect(function(face, distance)
local moveDistance = distance * grid -- Scale the drag distance by grid value
if lastDistance ~= moveDistance then
-- Calculate the movement direction based on the face normal
local moveDirection = part.CFrame:vectorToWorldSpace(Vector3.FromNormalId(face)).Unit * moveDistance
-- Update part's position based on the movement
part.Position = lastPosition + moveDirection -- Use lastPosition as reference to calculate new position
lastDistance = moveDistance -- Store the moved distance for comparison
end
end)
Minor Mistake: grid manages how much you have to drag to move it, not the snapping grid one. Sorry about that