banner



How To Fullscreen Unity Camera

Fullscreen is piece of cake, right? Unity handles information technology for you, and yous can e'er just set Screen.fullScreen, right?

Well, aye and no. There are some weird quirks in Unity's fullscreen implementation, at least on Mac. I oasis't verified whether these problems also exist on Windows, merely the workarounds I came up with don't break annihilation on Windows, so they're safe to utilise (equally far as I'm enlightened).

Unity has some issues with fullscreen

If you have any questions about this article or virtually Unity evolution, you can find me in my discord server : https://discord.gg/zeCKc8SnHs

The problem

Allow'southward start with a blank Unity project. I set it to 2nd (merely the issue applies to 3D as well), and set the camera to clear to a prissy solid color.

To demonstrate the issue properly, I checked the "Resizable Window" setting in the player settings.

After building, our "game" looks like this, filling the screen nicely :

Initially, full screen works equally expected

Now let's exit fullscreen, and resize the window to something a flake more than vertical :

Scaling the window to a different aspect ratio

At present if you enter fullscreen over again, this happens :

Oh no! Unity is keeping the scaled aspect ratio in fullscreen mode!

Unity keeps the dimensions of the window, scales it up to fit, and letterboxes it. This conspicuously is a scrap of an issue.

You might call up that turning off "Resizable Window" would solve this issue. Well, only kind of. On Mac, you can withal somewhat resize the window with the Zoom (Maximize) button, enough to brand some letterboxing happen. And also, not-resizable windows aren't keen for the user.

It's also of import to note that this issue exists in both 'Fullscreen Window' and 'Exclusive Fullscreen' modes.

The solution

There may be a much simpler solution to this than what I'm presenting — if in that location is, delight allow me know. Merely I've seen a coupe of indie games that practice non address this issue at all, and then I figured information technology would be worthwhile to share my solution.

My solution works by detecting a change in fullscreen like and so :

          if (Screen.fullScreen != prevFullScreen) {
if(Screen.fullScreen) {
// We just entered fullscreen
} else {
// We just left fullscreen
}
prevFullScreen = Screen.fullScreen;
}

Entering fullscreen

When nosotros enter fullscreen, nosotros manually set the resolution to… some resolution. Just which i?

If you have a settings screen where users tin can modify the resolution, and they've previously selected a resolution, that would be a skilful choice. But merely if that resolution is still nowadays in the list of bachelor resolutions (Screen.resolutions). After all, they may be using a unlike screen at present.

But if they haven't picked a resolution yet (ie information technology's the first fourth dimension they're playing) — or the previously selected resolution isn't bachelor anymore, we demand to pick some default value.

For these cases, a safe bet would be to pick the last resolution in the Screen.resolutions array. As far as I tin tell, the last entry is unremarkably either the currently selected organisation resolution, or the highest natively supported resolution supported by the screen+gpu combo.

But just for completeness, I want to present a couple of other options that I came across while researching how to selection a default resolution.

  • In that location's Screen.currentResolution which gives you the OS'es resolution, but it's allegedly but accurate while you're in windowed mode. Just you lot could outset your game in windowed mode, grab this resolution and shop it.
  • Another option is using Display.master.systemWidth and Display.primary.systemHeight. An event with these is that for "retina" displays, they give you half of the actual physical resolution. One affair yous could do is checking if (Brandish.main.systemWidth * ii, Brandish.main.systemHeight * 2) is a supported resolution in Screen.resolutions. If it is, that might be a good default resolution to option as a default. If it's not, you can check if (Display.main.systemWidth, Brandish.main.systemHeight) is supported.

In that location are some other caveats to picking a default resolution. On Mac, it'southward possible for the Bone to render to a higher resolution than the screen supports, and scale downwards. When they do this, this higher resolution would appear at the start of the Screen.resolutions array, even though information technology may be a resolution that's as well high for the GPU to back up (on the 2015 5K iMacs this is an effect, for instance). This is hard to find, but yous might desire to filter out resolutions that yous deem too loftier. For most games, supporting up to 4K or 5K is probably enough.

But when filtering out resolutions that you deem likewise high, there's always the possibility that the Screen.resolutions list doesn't contain anything else. I'm non sure if this would always happen, but it'due south still good practice to try to grab whatsoever potential bugs. So if filtering out entries leaves you with an empty array, revert to the unfiltered list.

Exiting fullscreen

When the user exits fullscreen, I like scaling the window to about half the size of the screen. Usually, I have a list of preferred windowed sizes, and selection the one that'due south slightly smaller than one-half the screen size.

Enough talk, prove me the code

Hither'due south an instance of how to handle this. This is a rewrite of my code, fabricated for this tutorial, so it hasn't been tested in a real game. I did test it, just do let me know if y'all discover whatever bug.

I recommend trying to understand the code, and adapt it to suit your needs. Not every game will take the verbal same requirements.

It'due south quite elaborate, but it'due south non rocket scientific discipline. Information technology might exist over-engineered a bit, and so I'grand definitely interested if anyone knows a simpler solution.

Since Medium doesn't have syntax highlighting, I too posted the code here : https://pastebin.com/y7kf7s7F

          using System;
using System.Collections.Generic;
using UnityEngine;
public grade FullScreenManager : MonoBehaviour {
public static FullScreenManager instance;
// Update this list to contain your preferred window sizes for windowed manner, from large to small
private Listing<Vector2Int> windowedResolutions = new Listing<Vector2Int> {
new Vector2Int(2560, 1440),
new Vector2Int(1920, 1080),
new Vector2Int(1280, 720),
new Vector2Int(640, 360),
new Vector2Int(320, 180)
};
private bool prevFullScreen; // If needed, you can ready PreferredWidth and PreferredHeight from your settings screen private int? _preferredWidth = aught;
// PreferredWidth will render 0 if this hasn't been set before
public int PreferredWidth {
go {
if (_preferredWidth == null) _preferredWidth = PlayerPrefs.GetInt ("PreferredResolutionWidth", 0);
return (int)_preferredWidth;
}
gear up {
if (value != _preferredWidth) {
_preferredWidth = value;
PlayerPrefs.SetInt ("PreferredResolutionWidth", value);
}
}
}
individual int? _preferredHeight = null;
// PreferredHeight will return 0 if this hasn't been set earlier
public int PreferredHeight {
go {
if (_preferredHeight == nada) _preferredHeight = PlayerPrefs.GetInt ("PreferredResolutionHeight", 0);
render (int)_preferredHeight;
}
set {
if (value != _preferredHeight) {
_preferredHeight = value;
PlayerPrefs.SetInt ("PreferredResolutionHeight", value);
}
}
}
void Start () {
if (instance != zip) {
// If an instance already exists, we disable this i.
// It will remain in the hierarchy, merely that'south fine. I prefer this over destroying, less work for the GC
gameObject.SetActive (false);
return;
}
DontDestroyOnLoad (gameObject);
instance = this;
// Start upward in fullscreen
// Yous could also shop the previous state and use that when reopening
SetupFullscreen ();
}
void Update () {
if (Screen.fullScreen != prevFullScreen) {
if (Screen.fullScreen) {
SetupFullscreen ();
} else {
SetupWindowed ();
}
prevFullScreen = Screen.fullScreen;
}
}
private void SetupFullscreen () {
if(PreferredWidth != 0 && PreferredHeight != 0) {
// We have previous settings, check if it's available
if(ResolutionAvailable(PreferredWidth, PreferredHeight)) {
SetFullScreenResolution (PreferredWidth, PreferredHeight);
return;
}
}
// Find the first resolution <= 5K
for (var i = Screen.resolutions.Length - i; i >= 0; i--) {
Resolution res = Screen.resolutions[i];
if(res.width <= 5120) {
SetFullScreenResolution (res.width, res.height);
return;
}
}
// There wasn't a resolution <= 5K... Try the beginning matter in the resolutions assortment
if(Screen.resolutions.Length > 0) {
Resolution highest = Screen.resolutions[Screen.resolutions.Length - 1];
SetFullScreenResolution (highest.width, highest.height);
render;
}
// Nothing in the Screen.resolutions array? Not sure if this will ever happen, but permit'southward effort Screen.display
SetFullScreenResolution (Display.main.systemWidth, Display.primary.systemHeight);
} individual bool ResolutionAvailable (int preferredWidth, int preferredHeight) {
foreach(var res in Screen.resolutions) {
if(res.width == preferredWidth && res.elevation == preferredHeight) {
return true;
}
}
return simulated;
}
individual void SetupWindowed () {
// Let's try to find a resolution equal to or smaller than half the screen width
// It needs to also fit the height
for (int i = 0; i < windowedResolutions.Count; i++) {
var res = windowedResolutions[i];
if(res.x <= Screen.currentResolution.width / 2 && res.y <= Screen.currentResolution.height) {
SetWindowedResolution (res.x, res.y);
return;
}
}
// If nada matched, let'south go the other way and find the offset ane that's wider than one-half the screen width
for (int i = windowedResolutions.Count - 1; i >= 0; i--) {
var res = windowedResolutions[i];
if (res.x >= Screen.currentResolution.width / 2 && res.y <= Screen.currentResolution.superlative) {
SetWindowedResolution (res.10, res.y);
return;
}
}
// Only for sanity'southward sake, fall dorsum to the smallest resolution in the listing
var last = windowedResolutions[windowedResolutions.Count - 1];
SetWindowedResolution (last.x, last.y);
}
individual void SetFullScreenResolution (int width, int height) {
// For my games, I prefer ExclusiveFullScreen with a fixed refresh charge per unit of 60hz.
Screen.SetResolution (width, height, FullScreenMode.ExclusiveFullScreen, 60);
}
private void SetWindowedResolution (int width, int height) {
Screen.SetResolution (width, height, FullScreenMode.Windowed, 60);
}
}

And that's information technology. If you observe any issues with this snippet, please allow me know.

If you need aid with this code or if y'all have other Unity-related questions, there'due south a #game-dev-communication channel in my Discord : https://discord.gg/zeCKc8SnHs

Source: https://gamesfromearth.medium.com/dealing-with-fullscreen-in-unity-43b7673f9732

Posted by: bermangreirrom.blogspot.com

0 Response to "How To Fullscreen Unity Camera"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel