I'm trying to create an equivalent to the default ROBLOX 'Drag' HopperBin, but I want it to only work within a 20 stud radius. I've got that bit working, but actually moving the part I'm dragging is not how I'd like it. I want it 'rounded' to the nearest stud. The problem with that is that some studs are .5 and not just a solid 1. Here's my current code:
local player = script.Parent.Parent.Parent.Parent local mouse = player:GetMouse() local draggable = false local trg = nil
mouse.Move:connect(function()
if trg ~= nil then
if mouse.Target ~= trg then
if (mouse.Hit.p - trg.Position).magnitude <= 50 then
trg.Position = Vector3.new(math.ceil(mouse.Hit.p.X),math.ceil(mouse.Hit.p.Y),math.ceil(mouse.Hit.p.Z))
end
end
end
end)
mouse.Button1Down:connect(function()
if mouse.Target ~= nil then
if mouse.Target:findFirstChild("ForageItem") ~= nil then
if mouse.Target:findFirstChild("ForageItem").RemoveOnForage.Value == true then
if mouse.Target:findFirstChild("NoDrag") == nil then
if player.Character ~= nil then
if (mouse.Target.Position - player.Character:GetModelCFrame().p).magnitude <= 50 then
trg = mouse.Target
end
end
end
end
end
if draggable == true and trg ~= nil then
trg.Rotation = Vector3.new(0,0,0)
local sel = Instance.new("SelectionBox",player.PlayerGui)
sel.Adornee = trg
sel.Name = "DragBox"
sel.Color = BrickColor.new("Bright blue")
trg.Anchored = true
else
if player.PlayerGui:findFirstChild("DragBox") ~= nil then
player.PlayerGui:findFirstChild("DragBox"):Destroy()
end
end
end
end)
mouse.KeyDown:connect(function(key)
if key == "r" then
trg.CFrame = trg.CFrame * CFrame.Angles(0,math.pi/2,0)
elseif key == "t" then
trg.CFrame = trg.CFrame * CFrame.Angles(0,0,math.pi/2)
if trg.Rotation.Z == 90 then
trg.Position = trg.Position + Vector3.new(0,2,0)
end
end
end)
mouse.Button1Up:connect(function()
if player.PlayerGui:findFirstChild("DragBox") ~= nil then
player.PlayerGui:findFirstChild("DragBox"):Destroy()
end
if trg ~= nil then
trg.Anchored = false
for i=1,10 do
trg = nil
end
end
end)
coroutine.resume(coroutine.create(function()
while true do
wait(0.01)
if player.PlayerGui.TopBar.Selected.Value == "Drag" then
script.Parent.Visible = true
script.Parent.Position = UDim2.new(0,mouse.X + 10,0,mouse.Y + 40)
local passed = false
if mouse.Target ~= nil then
if mouse.Target:findFirstChild("ForageItem") ~= nil then
if mouse.Target:findFirstChild("ForageItem").RemoveOnForage.Value == true then
if mouse.Target:findFirstChild("NoDrag") == nil then
if player.Character ~= nil then
if (mouse.Target.Position - player.Character:GetModelCFrame().p).magnitude <= 50 then
passed = true
end
end
end
end
end
end
if passed == false then
script.Parent.Text = "Not Draggable"
script.Parent.TextColor3 = Color3.new(255/255,0,0)
else
script.Parent.Text = "Draggable"
script.Parent.TextColor3 = Color3.new(0,255/255,0)
end
draggable = passed
else
script.Parent.Visible = false
end
end
end))

3 comments
What is the second argument to the function? Vector3.unit?
No, it's not an argument of Vector3 API. The unit is argument of my custom function, and I use it to round to closest value using modulus operator. What I am doing, is: vector.X - (vector.X % 20) In that example it would snap X to 20 stud grid.
Thank you! I worked it out! :)