(MULTI SELECTION) Selecting everything 3d stuff inside a frame?

TLDR: How to detect every 3d stuff inside a 2d frame? Making a 3d part same size as a 2d frame’s pixels is gonna make the 3d part HUGE: HOW TO FIX

----------------------------------------------------------------------------------------------------------

  • I am currently tryna make a rts game…

  • I just started and I am pretty lost already.

  • I decided to work on a selection thingy.

  • selectionGif
    I want to know everything that is inside that viewport frame.

  • I thought of making a blockcast the same size of the viewport frame and make the cframe and direction the player’s camera. (this is probabbly a very bad way)

  • I decided to prototype the block cast system using a part.

local selectionBoxSize = selectionFrame.Size
local blockCastSize = Vector3.new(selectionBoxSize.X.Offset, selectionBoxSize.Y.Offset, 5) -- the z value will determine the length
local debugPart = Instance.new('Part', workspace)

debugPart.Transparency = .5
debugPart.CanCollide = false
debugPart.Anchored = true
debugPart.CFrame = workspace.CurrentCamera.CFrame
debugPart.Size = blockCastSize
  • But the problem is, this system makes the "debugPart* REALLY BIG.
    HUGEshapecast

  • IDK how to fix this. I probabbly should be doing some kind of math ratio of pixel size to roblox studs but idk what it is or if its even the correct way.

  • If there is an easier way , please tell me.

2 Likes

This should be able to help you

2 Likes

I cant understand any of that math stuff :skull:
also where can i find that “build v4 source code” mentioned in the post

1 Like

If you wish to retrieve specific models, parts and such, try looking into CollectionService with it’s :AddTag(), :HasTag() and :GetTagged() methods, on top of that it’d be better to utilize CurrentCamera:WorldToViewportPoint()

An example code should go like this:

local models = CollectionService:GetTagged("Models") :: {Model}

local function getModelsFromPosition(a: Vector2, b: Vector2): boolean
   -- let a be the starting point of our click
   -- while b being the point where the release our click
   local list = {}
   for _, model in ipairs(models) do
      local pivot = model:GetPivot() :: CFrame
      local vector, isOnScreen = CurrentCamera:WorldToViewportPoint(pivot.Position) :: Vector3, boolean
      if isOnScreen and (
          ( -- our A is top left while B is bottom right
              (vector.X > a.X and vector.Y < a.Y) and -- check if our X is greater than a's X position but lower than a's Y position
              (vector.X < b.X and vector.Y > b.Y) -- check if our X is less than b's X position but higher than b's Y position
          ) or ( -- B is top left while A is bottom right
              -- just invert the conditions from above
          )
      then
          table.insert(list, model)
      end
   end
   return list
end
2 Likes

hey it doesnt work for me.

for _, unit in units do
			local pivot = unit:GetPivot() :: CFrame
			local  screenPosForUnit, isOnScreen = workspace.CurrentCamera:WorldToViewportPoint(pivot.Position) 
			
			print(screenPosForUnit)
			if isOnScreen then
				print(unit, "iss in the sscreen") -- passed
				if ((screenPosForUnit.X > startPoint.X and screenPosForUnit.Y < startPoint.Y) and (screenPosForUnit.X < endPoint.X and screenPosForUnit.Y > endPoint.Y))  or  ((screenPosForUnit.X < startPoint.X and screenPosForUnit.Y > startPoint.Y) and (screenPosForUnit.X > endPoint.X and screenPosForUnit.Y < endPoint.Y))	then
					table.insert(selection, unit)
					print(unit , " is in!") -- failed
				end
			end
		end
1 Like

Create a 3d hit box, filter out not needed elements, only the humanoid root parts, unless you have your own system then even better. Set height of the bounding box to something to a really big number like 500 and get both ends of the bounding box by raycasting the positions from the player’s view. Everything is done, you have point A and B and you are good to go with the selector view module.

2 Likes

thats what im trying to do.
but the problem was that making the size for the part equal to the frame made the part very huge.
to battle this i’d need to take in account for the distance between the camera and selection area, fov and the ratio of pixels to studs in roblox studio and i have no idea how :moyai:

function isInBound(BoundingBox2D,Object : Part)
     BoundingBox2D.A = Vector2.new(math.min(BoundingBox2D.A.x,BoundingBox2D.B.x),math.min(BoundingBox2D.A.y,BoundingBox2D.B.y));
     BoundingBox2D.B = Vector2.new(math.max(BoundingBox2D.A.x,BoundingBox2D.B.x),math.max(BoundingBox2D.A.y,BoundingBox2D.B.y));
     local Vec2 = _G.Camera:WorldToScreenPoint(Object.Position); //Converts world position of an object into clipspace of a camera.
     return (Vec2.x > BoundingBox2D.A.x and Vec2.x <= BoundingBox2D.B.x) and (Vec2.y > BoundingBox2D.A.y and Vec2.y <= BoundingBox2D.B.y)
end

can u explain what it does and what it reutrns?
what does that and do in return/
i am so confused what is boundingbox2d supposed to be/

Try tweaking with the 2nd if statement, and print screenPosForUnit, endPoint and startPoint

1 Like

okay, so uisng :WorldToScreenPoint() instead of :WorldToViewportPoint() and using the primary part’s CFrame. i was able to get accurate results and i updated the logic to;

				if ((screenPosForUnit.X > startPoint.X and screenPosForUnit.Y > startPoint.Y) and (screenPosForUnit.X < endPoint.X and screenPosForUnit.Y < endPoint.Y)) or ((screenPosForUnit.X < startPoint.X and screenPosForUnit.Y < startPoint.Y) and (screenPosForUnit.X > endPoint.X and screenPosForUnit.Y > endPoint.Y)) then

and it worked! thanks for your help.

2 Likes

Bounding box 2D is a table with defined values as A and B.

Value A is inputted by user at the start of selection click.
Value B is inputted when the selection click hold ends.
After this you check if every unit is in bound of the 2dbox, in the screenspace.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.