Creating a 2d selection system

I want to create a 2d to 3d selection system via mouse dragging. Unfortunately when I use region3, it either creates a part or it creates a really tiny part.

What I have:
I have the 2 points where I want a region to be at using rays but I’m unable to use Region3. I’ve read the Developer Hub but I’m genuinely confused if the second argument is where you want the other end to be at or the size so I’ve also calculated the sizing.

https://gyazo.com/fc3b4121e45e400c7c9742b8ce6ed9c4

Code:

--|| SERVICES ||--
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

--|| VARIABLES ||--
local Player = Players.LocalPlayer
local Camera = game.Workspace.CurrentCamera
local Mouse = Player:GetMouse()
local PlayerGui = Player:WaitForChild("PlayerGui")
local MainGUI = PlayerGui:WaitForChild("MainGUI")

--|| MODULES ||--
local GlobalFunctions = require(ReplicatedStorage.GlobalFunctions)

local Connections = {
	MouseMove = nil,
	MouseRelease = nil	
}

local function cleanUpConnections(exceptionList)
	for ConnectionName, Connection in pairs(Connections) do
		if not exceptionList[ConnectionName] then
			Connection:Disconnect()
			Connection = nil
		end
	end
end

Mouse.Button1Down:Connect(function()
	local x1,y1 = Mouse.X, Mouse.Y
	local x2,y2 = x1, y1
	
	--> Clean up any previous functions that may have exited
	cleanUpConnections({})
	
	Connections.MouseMove = Mouse.Move:Connect(function()
		x2 = Mouse.X
		y2 = Mouse.Y
		
		--> Changing the Anchor Point under certain conditions
		if x2 < x1 then
			MainGUI.SelectionFrame.AnchorPoint = Vector2.new(1,MainGUI.SelectionFrame.AnchorPoint.Y)
		else
			MainGUI.SelectionFrame.AnchorPoint = Vector2.new(0,MainGUI.SelectionFrame.AnchorPoint.Y)
		end
		
		if y2 < y1 then
			MainGUI.SelectionFrame.AnchorPoint = Vector2.new(MainGUI.SelectionFrame.AnchorPoint.X,1)
		else
			MainGUI.SelectionFrame.AnchorPoint = Vector2.new(MainGUI.SelectionFrame.AnchorPoint.X,0)
		end
		
		--> Changing the size
		MainGUI.SelectionFrame.Position = UDim2.new(0,x1,0,y1)
		MainGUI.SelectionFrame.Size = UDim2.new(0,math.sqrt((x2-x1)^2),0,math.sqrt((y2-y1)^2))
	end)
	
	Connections.MouseRelease = Mouse.Button1Up:Connect(function()
		MainGUI.SelectionFrame.Size = UDim2.new(0,0,0,0)
		MainGUI.SelectionFrame.AnchorPoint = Vector2.new(0,0)
		cleanUpConnections({})
		
		local pointX = Camera:ScreenPointToRay(x1,y1,1)
		local pointY = Camera:ScreenPointToRay(Mouse.X,Mouse.Y,1)
		local rayx = Ray.new(pointX.Origin, pointX.Origin + pointX.Direction*100)
		local rayy = Ray.new(pointY.Origin, pointY.Origin + pointY.Direction*100)
		local hitx, posx = game.Workspace:FindPartOnRayWithWhitelist(rayx, {game.Workspace.World})
		local hity, posy = game.Workspace:FindPartOnRayWithWhitelist(rayy, {game.Workspace.World})
		
		local sizeX = math.abs(posx.X - posy.X)
		local sizeY = math.abs(pointX.Origin.Y - posx.Y)
		local sizeZ = math.abs(posx.Z - posy.Z)
				
		GlobalFunctions.createVisualRay(pointX.Origin, pointX.Origin + pointX.Direction*100)
		GlobalFunctions.createVisualRay(pointY.Origin, pointY.Origin + pointY.Direction*100)

		local region = Region3.new(posx, posy)
		local Part = Instance.new("Part", game.Workspace)
		Part.CFrame = region.CFrame
		Part.Size = region.Size

--		local selectedRegion = Region3.new(posx, Vector3.new(sizeX,sizeY,sizeZ))
--		local res = 4
--		selectedRegion = selectedRegion:ExpandToGrid(res)
--		local terrain = game.Workspace:WaitForChild("Terrain")
--		terrain:FillRegion(selectedRegion, 4, Enum.Material.Water)

	end)
end)

return Connections
5 Likes

A likely reason it’s not working is because you are not accounting for scale or the size of the viewing frustum, what i mean is that the size of the region is the size of the actual positions in worldspace, it is relative to the actual size of the camera.


if you don’t need to use regions for your specific case, here is a useful post:

2 Likes

Region3 won’t really work in this case because it has no rotation. Try an invisible brick by cframing/resizing it and binding a random function to Touched so that it has a touchinterest. I think this is how that old “custom region3” script worked

1 Like

Oh, I plan to make the camera angle in a birds eye view looking down. My overall goal is to find any objects that overlap with the selection frame.

I found another function I believe it was called WorldToScreenPosition, I was wondering if I could search through everything in the world to see if it’s within the size of the selection frame.

My main issue is I’m not too sure how Region3 works. The reason I want to use Region3 is to prevent looping through the entire world and hope it helps improve in performance.

I’ve read the GetBoundingBox and it seems like it just finds all the descendants which means I could also use the WorldToScreenPosition method?

I really don’t recommend doing an exaughstive search for instances unless you check all corners and space of the bounding box and heavily limit the amount of items available for selection.

So would Region3 be a solution? Or could I create a part and use :GetTouchingParts()? Would these be better solutions?

EDIT: Overall, I do plan to have a folder of selectables so I’m not searching through every part, I also plan to use :GetChildren().

I have an article similar to this, maybe you could get some help from it!

Edit: Oops, just saw that @Jaycbee05 already said it.

Ah, yes. I’ve read upon that thread. @Jaycbee05 above has mentioned his response. I’m just not too sure how to work it out without any references. I’ve read the sample code and it seems like it gets descendants so I was wondering if I could use any of the other solutions above.

What do you mean by this? Is it working but not as expected?

Take a look at the gif, you can see that there are rays (The long parts) and then in the ground there are tiny parts glitching through the floor. I was running around basically using the select feature and one time it created a actual large part that seems to be to scale. The rest where just extremely tiny sticks.