I am currently looking to create a part that will effectively cover an entire computer screen (PC is the only supported device) based on its screen size. This is so that I can add effects to the camera1 using parts welded to it. I’ve run into a small, single difficulty: the size itself.
I don’t know how to make a part that’ll size well to the screen. Any tips?
I have tried using the ViewportSize of the Camera. That didn’t work as well as I hoped and instead created a giant part. I doubt the camera is able to view this far out. Image below: gray is the part intended to be attached to the camera CFrame, dark grey is the base plate.
1 Original intention was to put parts around the edge of the screen. Don’t feel like figuring that out, the one thread I saw doesn’t have a solution and looks complicated to me.
The part size cap is on each axis is 2048. Your workaround should be around using BlockMesh to scale beyond it. Here’s a screenshot of an incredibly large part using BlockMesh with high numbers on Scale.
ViewportSize are pixels. I don’t really know how to actually get the amount of pixels per studs in a fixed distance.
Doesn’t answer my question. I’m not looking to resize a part to the maximum extents, I’m only looking to do so until a part can cover my screen. BlockMesh doesn’t explain how I can accomplish this either, it’d oversize my brick larger than what’s in the linked image.
Not quite sure how I’m supposed to apply this or if it fits my use case. I tried looking through the code and I’m pretty confused. Doesn’t this module just cut the work of calculations for you? If so, this isn’t what I’m looking for either.
I have an idea, but I can’t seem to test it right now because roblox studio won’t open.
To avoid making huge parts (1080 studs by 800 studs) you can use math.clamp() to keep the part size to a minimum, while retaining the proportions. I’m thinking something like a maximum of 2,2.
The hard part is, you would have to find the correct distance from the camera to place the part. No clue how to do this, but I’m wondering if you might be able to use the difference between (max size - actual size)?
I have considered lamping the values to a certain size but this doesn’t adequately cover my use case because monitors that are potentially bigger than the clamped size will receive a smaller part covering their screen and make the effect really ugly. As for smaller screens, the part may be too large and instead produce an effect larger than their overall screen.
If providing a specific use case helps to determine how to resolve my problem or if there’s a better way to go about it, I can do so (since I noticed I did not provide one).
I would like to create part-based effects that depend on the edges of the screen. Specifically, I’m trying to align parts on the screen edges pointing towards the screen center in a cone-like form inward. These parts are going to be tweened or animated frequently.
Since the one solution I found does not adequately address my use case nor do I know how to tweak it in my favour, I’ve decided to retire reliance on screen edges and use a screen size to determine how big a part needs to be resized to cover a whole screen.
Thanks for adding your use case, was about to ask about that
What if you created 4 gui objects positioned at the corners of the screen (2d screengui) and then used workspace.CurrentCamera:ScreenPointToRay() with a unit of 1 (close to camera as possible) on each corner to get a world position to place your parts?
Sounds like an absolutely terrible workaround but an ingenious idea, exploiting API like that. If I can’t figure anything out within the next while, I’ll take this and mark it my choice of action.
Since this is just for a main menu, there shouldn’t be any actual issues. Most of the parts aren’t going to be moving outside of a fixed camera position.
The number of studs that would cover the screen depends on the camera’s field of view and the distance you want to put the covering part in front of the camera.
From the Developer Hub:
So using this property, you can find how many studs would cover the screen vertically at a certain distance from the camera:
And then the viewport size gives you the height-to-width aspect ratio of the screen, so the width would be
(viewportSize.x / viewportSize.y) * height
If you make a part that size and then CFrame it so that it’s offset from the camera by forwardOffsetDistance, I believe it should cover the entire screen.
I think the small error is due to you using the arctan function. I switched it to tangent (since FOV is an angle), dropped the 2 you multiplied by, and it worked fine when I tested it.
EDIT: I forgot to mention why I was able to drop the 2. I was only using an offset distance of 1, and the z size of the part I used was also 1, so when I set the part’s CFrame to the camera’s CFrame translated by the offset distance, it worked out.
Covers the screen completely through a few view tests. I may have to plug in some numbers to test and find a firm value of what I want since I hard-coded variables to test the code.
local cam = workspace.CurrentCamera
local viewportSize = cam.ViewportSize
local forwardOffsetDistance = 1
local height = math.tan( math.rad(cam.FieldOfView/2) ) * 2 * forwardOffsetDistance
local horizontal = (viewportSize.x / viewportSize.y) * height
workspace.Part.CFrame = cam.CFrame * CFrame.new(0, 0, -0.1)
workspace.Part.Size = Vector3.new(height, horizontal, 0.1)
Just the size is a little small because I moved the part away a bit. If I don’t CFrame it out, it covers the whole screen but doesn’t show due to it being within the Z clip. The part itself doesn’t have to show, since I’m attaching things to it. Screen view:
FWIW, here’s how to do it with the ScreenSpace module:
local ScreenSpace = require(script.ScreenSpace)
local ViewSizeX = ScreenSpace.ViewSizeX()
local ViewSizeY = ScreenSpace.ViewSizeY()
local Depth = 5 -- Distance from camera to part
workspace.Part.CFrame = workspace.CurrentCamera.CFrame * CFrame.new(0, 0, -Depth - 0.5)
workspace.Part.Size = Vector3.new(
ScreenSpace.ScreenWidthToWorldWidth(ViewSizeX, -Depth),
ScreenSpace.ScreenHeightToWorldHeight(ViewSizeY, -Depth),
1
)