Selection with mouse

Here’s what I am trying to achieve, but I have no idea how to do it: https://gyazo.com/fdf2cc82a1e9e21bf68d91d1a8edfb4f
Any help is appreciated

1 Like

I believe you could use Region3 but I haven’t really figure out that yet :sweat:

1 Like

Yeah I am guessing so, but I have no idea hot to implement it :cry:

1 Like

Take a look at its API: Region3 | Documentation - Roblox Creator Hub

1 Like

I did, but I am not sure what to look at specifically, please help.

@alexfinger21

You can create a Region3 in the position of the mouse using mouse.Hit.p then, make a loop to get all the parts/models inside of the Region3 and do whatever you want the object in the Region3 to do.

To replicate the screen selection box:

  • Create a dynamic rectangle UI
  • Note down the two points: when the mouse was pressed and when it was released
  • Size the UI by the change in x and y of the two points, position should be the center of the two points, half of their x and y sum.

To select from world view:

  • Grab all the interactive model’s screen position by using WorldToScreenPoint
  • Check if they are within the rectangle area by comparing the screen points.
1 Like

Could you maybe give me some script examples, that’s old be really helpful.

A good place to start is Camera:ViewportPointToRay. You could run through each pixel of your box with this function, and then raycast outward like so:

local ray = Camera:ViewportPointToRay(x, y)

local raycastResult = workspace:Raycast(ray.Origin, ray.Direction * 500) 
if raycastResult then 
    if raycastResult.Instance == [Your Part here] then
        --You have a part, now select it! 
    end
end 

In order for this to function properly, I would add each unit selected into a list and make sure you are not selecting a part more than once like so:

local ray = Camera:ViewportPointToRay(x, y)
local selectedUnits = {} 

local raycastResult = workspace:Raycast(ray.Origin, ray.Direction * 500) 
if raycastResult then 
    if raycastResult.Instance == [Your Part here] and not table.find(selectedUnits raycastResult.Instance) then
        --You have a part, now select it! 

       table.insert(selectedUnits, raycastResult.Instance) 
    end
end 
2 Likes

This is a good solution, but would get laggy really quickly depending on the size of the game

That is debatable, as there are steps you could take for optimization. Such as caching a table of the screen points and only comparing the positions if they are within the screen size.

As long as the number of interactables does not exceed the number of pixels within the selection box, this will be more efficient. And that is to assume that there will always be hundreds of interactables ingame.

1 Like

I just cooked up a simple selection tool.

local Frame = script.Parent:WaitForChild("Frame")
Frame.AnchorPoint = Vector2.new(0.5, 0.5)

local Camera = game.Workspace.CurrentCamera
local Mouse = game.Players.LocalPlayer:GetMouse()

local mouseReleased do
	
	Mouse.Button1Down:Connect(function()
		
		local mouseDown = Vector2.new(Mouse.X, Mouse.Y)
		mouseReleased = nil
		
		local selection = Frame:Clone()
		selection.Parent = Frame.Parent
		selection.Visible = true
		
		while not mouseReleased do
			local mouseLocation = Vector2.new(Mouse.X, Mouse.Y)
			
			selection.Size = UDim2.new(0, math.abs(mouseDown.X - mouseLocation.X), 0, math.abs(mouseDown.Y - mouseLocation.Y))
			selection.Position = UDim2.new(0, (mouseDown.X + mouseLocation.X) / 2, 0, (mouseDown.Y + mouseLocation.Y) / 2)
			
			wait()
		end
		
		selection:Destroy()
	end)

	Mouse.Button1Up:Connect(function()
		mouseReleased = true
	end)
end

https://venyx.wtf/medias/uA4L9Ljrhr.mp4

1 Like

Thank you! I will use worldpositiontopoint in order to get the position.

How do I detect if a point is in the Gui? so like that position is in the position of the gui.

Comparing both points as vector2 (screen point), check if the x is not greater than the max x and not less than the minimum x, same goes for y.

Here is the condition that is applied to all interactable

local positionX, positionY = selection.AbsolutePosition.X, selection.AbsolutePosition.Y
local sizeX, sizeY = selection.AbsoluteSize.X / 2, selection.AbsoluteSize.Y / 2

local minX, maxX = positionX - sizeX, positionX + sizeX
local minY, maxY = positionY - sizeY, positionY + sizeY

local screenPoint, inView = game.Workspace.CurrentCamera:WorldToScreenPoint(interactable.Position)

if inView then
    if math.clamp(screenPoint.X, minX, maxX) == screenPoint.X and math.clamp(screenPoint.Y, minY, maxY) == screenPoint.Y then
        -- select interactable
    end
end

I already figured it out, but thank you

Also, to anyone wondering, I got much better at scripting, and what is more effective to use is actually creating a region3 based on one position that’s 10 studs below the time the player held down the mouse, and the other position 10 studs up when the player released the mouse.

Unrelated, but that’s good music :slight_smile: