Dealing with field of view
First of all, since your play field is mostly horizontal, you’ll probably want the horizontal FoV to be the same for all players, rather than the vertical FoV. The Camera.FieldOfView
property sets the vertical FoV, so you’ll have to do some calculations to figure out which vertical FoV results in the desired horizontal FoV with the current screen aspect ratio.
Here are functions for *calculating* the vertical and horizontal FoV, given a screen and a camera:
Note that the getVerticalFov
function is pretty redundant because you can just get that number with CurrentCamera.FieldOfView
. But it gives a good idea of how the calculation works.
function getVerticalFov(camera)
return camera.FieldOfView
--Equivalent calculation:
--local z = camera.NearPlaneZ
--local viewSize = camera.ViewportSize
--
--local r0, r1 =
-- camera:ViewportPointToRay(viewSize.X/2, viewSize.Y*0, z),
-- camera:ViewportPointToRay(viewSize.X/2, viewSize.Y*1, z)
--
--return math.deg(math.acos(r0.Direction.Unit:Dot(r1.Direction.Unit)))
end
function getHorizontalFov(camera)
local z = camera.NearPlaneZ
local viewSize = camera.ViewportSize
local r0, r1 =
camera:ViewportPointToRay(viewSize.X*0, viewSize.Y/2, z),
camera:ViewportPointToRay(viewSize.X*1, viewSize.Y/2, z)
return math.deg(math.acos(r0.Direction.Unit:Dot(r1.Direction.Unit)))
end
Here's a function for calculating the camera aspect ratio (apparently not the same as screen FoV?)
function getAspectRatio(camera)
--Apparently this is not the same as
-- screen.AbsoluteSize.X / screen.AbsoluteSize.Y
--In my tests, only the current version gave the correct result
return camera.ViewportSize.X / camera.ViewportSize.Y
end
Here are functions for setting either the vertical for horizontal FoV
function setVerticalFov(camera, fov)
camera.FieldOfView = fov
end
function setHorizontalFov(camera, fov)
local aspectRatio = getHorizontalFov(camera)/getVerticalFov(camera)
camera.FieldOfView = fov / aspectRatio
end
Here are some screenshots showing exactly what happens when setting the horizontal FoV instead of the vertical FoV:
At aspect- ratio near 1 to 1:
At aspect- ratio closer to 2 to 1:
Notice how the horizontal FoV (in the output window) stays at 80 (because that’s what I set it to) between the two aspect- ratios. Also notice how the two red balls are always near the left and right edges of the screen, no matter how it’s stretched. The opposite is the case if you keep the vertical FoV constant. In that case, balls near the top and bottom edges of the screen will remain so when the screen is stretched.
Here's an example script showing how you can make sure the camera always has a fixed horizontal FoV, even if the player resizes the game window:
-- Keep a constant horizontal FoV. Put in game.Players.StarterPlayerScripts
-- Set the horizontal FoV at the start of the came
setHorizontalFov(camera, 80)
-- Set it every time the camera viewport changes size
camera:GetPropertyChangedSignal("ViewportSize"):Connect(function()
setHorizontalFov(camera, 80)
end)
Dealing with aspect ratio
As for making sure the player can only every see enough of the screen to force a certain aspect ratio, you’ll have to adjust the black bars. At aspect rations less than 16:9 you’ll need horizontal bars like in your example picture, and for aspect ratios greater than 16:9 you’ll need vertical bars at the sides of the screen. You don’t actually need a script for this, since the GuiElement.AnchorPoint
property was released. Just create a setup like this:
- Check
BlackBars.IgnoreGuiInset
.
- Set
UiAspectRatioConstraint.AspectRatio
to 1.778
(which is approximately 16/9).
- Set
UiAspectRatioConstraint.AspectType
to ScaleWithParentSize
.
-
UiAspectRatioConstraint.DominantAxis = Height
.
- The
AnchorPoint
of BarLeft
should be (1, 0)
.
-
BarRight.AnchorPoint = (0, 0)
.
-
BarTop.AnchorPoint = (0, 1)
.
-
BarBottom.AnchorPoint = (0, 0)
.
- Set the
Size
of each bar Frame
to (10, 0, 10, 0)
You can change the 10
's to even bigger numbers, if you expect any player to ever have an aspect ratio greater than 10:1 or less than 1:10. If those numbers aren’t big enough, the black bars might not fill the entire space that they should.
Screenshots of aspect ration- forcing black bars
If screen is wider than 16:9 (e.g. phones, widescreen PCs)
Notice the gap in the upper left corner. That’s because I forgot to check BlackBars.IgnoreGuiInset
.
If screen is narrower than 16:9 (e.g. older monitors)
You can add textures to make it look a bit prettier/less jarring. Or just pick a less contrasty- color than black.
: D
So I hope that’s helpful. It was pretty interesting figuring out how to calculate/set the horizontal FoV, and the black bars were surprisingly easy with Roblox’s UI constraint tools. Let me know if you have any questions, if anything is unclear or you don’t understand parts of the code. In case you can’t get stuff to work, here’s a place file Horizontal FOV.rbxl (21.0 KB)