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.
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 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
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
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.
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
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
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
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.