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
I believe you could use Region3 but I haven’t really figure out that yet
Yeah I am guessing so, but I have no idea hot to implement it
I did, but I am not sure what to look at specifically, please help.
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.
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
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.
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
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