Could anyone look over and simplify/shorten/optimize my selection box?

Here’s the game download: SelectionBoxOnly.rbxl (58.3 KB)

And here’s the code:

local startPos
local holding = false
local hasMoved = false
local dragThreshold = 10 

local function BindToMouseButton1Function(actionName, inputState, inputObj)
	
	if inputState == Enum.UserInputState.Begin then

		startPos = Vector2.new(Mouse.X, Mouse.Y)
		selectionBox.Position = UDim2.fromOffset(startPos.X, startPos.Y)
		selectionBox.Size = UDim2.new(0, 0, 0, 0)
		selectionBox.Visible = true
		holding = true
		hasMoved = false
		
	elseif inputState == Enum.UserInputState.End and holding == true then
		
		holding = false
		selectionBox.Visible = false

		if hasMoved ~= true then
			print("Clicked", selectionBox) -- replace with clicked function
		end
	
	end
	
end

local function BindToMouseMovementFunction()
	if holding == true then
		
		local currentPos = Vector2.new(Mouse.X, Mouse.Y)
		
		selectionBox.Size = UDim2.new(0,(currentPos.X - startPos.X), 0, (currentPos.Y - startPos.Y))
		selectionBox.Position = UDim2.new(0,startPos.X,0,startPos.Y)

		if hasMoved == false then
			if (currentPos - startPos).Magnitude > dragThreshold then
				hasMoved = true
			end
		else 
			print("Dragged", selectionBox) -- replace with drag function
		end
		
	end
end

ContextActionService:BindAction("BindActionMouseButton1", BindToMouseButton1Function, false, Enum.UserInputType.MouseButton1)
ContextActionService:BindAction("BindActionMouseMovement", BindToMouseMovementFunction, false, Enum.UserInputType.MouseMovement)

Thanks!

seem likes there’s a lot of Boolean, let me try:

local startPos, holding, hasMoved, dragThreshold = nil, false, false, 10

local function BindToMouseButton1Function(actionName, inputState, inputObj)

	if inputState == Enum.UserInputState.Begin then

		startPos = Vector2.new(Mouse.X, Mouse.Y)
		selectionBox.Position = UDim2.fromOffset(startPos.X, startPos.Y)
		selectionBox.Size = UDim2.new(0, 0, 0, 0)
		selectionBox.Visible, holding = true
		hasMoved = false

	elseif holding and inputState == Enum.UserInputState.End then

		selectionBox.Visible, holding = false

		if not hasMoved then print("Clicked", selectionBox) end

	end
end

local function BindToMouseMovementFunction()
	
	if holding then
		
		local currentPos = Vector2.new(Mouse.X, Mouse.Y)

		selectionBox.Size = UDim2.new(0,(currentPos.X - startPos.X), 0, (currentPos.Y - startPos.Y))
		selectionBox.Position = UDim2.new(0,startPos.X,0,startPos.Y)

		if not hasMoved and (currentPos - startPos).Magnitude > dragThreshold then
		
			hasMoved = true
		
			return
				
		end
		
		print("Dragged", selectionBox) -- replace with drag function
		
	end
end

ContextActionService:BindAction("BindActionMouseButton1", BindToMouseButton1Function, false, Enum.UserInputType.MouseButton1)
ContextActionService:BindAction("BindActionMouseMovement", BindToMouseMovementFunction, false, Enum.UserInputType.MouseMovement)

Btw what is selectionBox, Mouse and ContextActionService?

you can try this too, but I don’t recommend cuz it’s not readable
if you do it for fun then do it :slight_smile:

pain:

local startPos, holding, hasMoved, dragThreshold = nil, false, false, 10; local function BindToMouseButton1Function(actionName, inputState, inputObj)if inputState == Enum.UserInputState.Begin then startPos = Vector2.new(Mouse.X, Mouse.Y)selectionBox.Position = UDim2.fromOffset(startPos.X, startPos.Y)selectionBox.Size = UDim2.new(0, 0, 0, 0)selectionBox.Visible, holding = true hasMoved = false elseif holding and inputState == Enum.UserInputState.End then selectionBox.Visible, holding = false if not hasMoved then print("Clicked", selectionBox) end end end local function BindToMouseMovementFunction() if holding then local currentPos = Vector2.new(Mouse.X, Mouse.Y)selectionBox.Size = UDim2.new(0,(currentPos.X - startPos.X), 0, (currentPos.Y - startPos.Y))selectionBox.Position = UDim2.new(0,startPos.X,0,startPos.Y)if not hasMoved and (currentPos - startPos).Magnitude > dragThreshold then hasMoved = true return end print("Dragged", selectionBox) end end ContextActionService:BindAction("BindActionMouseButton1", BindToMouseButton1Function, false, Enum.UserInputType.MouseButton1) ContextActionService:BindAction("BindActionMouseMovement", BindToMouseMovementFunction, false, Enum.UserInputType.MouseMovement)

It would be slightly more efficient to put the components into locals.

local x, y = Mouse.X, Mouse.Y
startPos = Vector2.new(x, y)
selecitonBox.Position = UDim2.fromOffset(x, y)

This line should be moved into BindToMouseButton1Function since it never changes, however you already have that, so just remove this.

You could marginally simplify if statements by only putting boolean variables in alone. This is purely style.

elseif inputState == Enum.UserInputState.End and holding then
...
if not hasMoved then
...
if holding then
...
if not hasMoved then -- You should invert this instead since you use the else statement here

Best attempt at optimization

You can optimize out creating new Vector2s by using only the components. Avoiding creating new objects is the best source of optimization I could see. As a final micro-optimization, you can have dragThreshold be the squared value of the target threshold and calculate the squared distance (avoiding needing to create an object or doing a square root operation).

local startX, startY
...
local dragThresholdSqr = dragThreshold ^ 2 -- Squared distance to avoid doing a square root

local function BindToMouseButton1Function(actionName, inputState, inputObj)
	...
		-- It should be marginally faster to use a local instead of an upvalue
		local x, y = Mouse.X, Mouse.Y
		startX, startY = x, y
		selectionBox.Position = UDim2.fromOffset(x, y)
		...

local function BindToMouseMovementFunction()
	...
		local currentX, currentY = Mouse.X, Mouse.Y
		-- Not sure if fromOffset is faster, but assuming it might be..
		selectionBox.Size = UDim2.fromOffset(currentX - startX, currentY - startY)

		if hasMoved == false then
			-- Manually calculated the squared distance
			if ((startX - currentX) ^ 2 + (startY - currentY) ^ 2) > dragThresholdSqr then
				...
1 Like