Scripting HelpersARCHIVE
A little piece of Roblox history. Preserved for everyone, one question at a time.Read about the archive →
✓ ANSWER ACCEPTED

How can I 'round' a Vector3 to the nearest stud?

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))

1 answer

✓ Accepted answer

I think this should work. Just tested with single number, so it should work with vectors just fine.

function roundVector(vector, unit)
	return vector - Vector3.new(vector.X%unit, vector.Y%unit, vector.Z%unit)
end

3 comments

0

What is the second argument to the function? Vector3.unit?

0

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.

0

Thank you! I worked it out! :)

This discussion is preserved as it was. New answers, comments, and votes are closed.