Search Issue Tracker
Fixed in Unity 2018.3
Screen.SetResolution(width, height, fullscreenMode) disregards resolution when changing to ExclusiveFullscreen
How to reproduce:
1. Open attached project "RobotFactorySimplified.zip" and build/run the application
2. In the application go to "Settings" menu
3. Change "Display Mode" to "Fullscreen" and "Screen Resolution" to native, apply changes with "Apply Changes" button (skip it if its already done)
4. Change "Display Mode" to "Borderless Window" and "Screen Resolution" to "640x480", apply changes
5. Change "Display Mode" to "Fullscreen", apply changes
6. Observe built application visual quality/resolution
Expected result: the resolution is "640x480", no application freeze in the process
Actual result: the application loads with native resolution and "Screen Resolution" shows 640x480 (if the menus are not responsive minimize the application)
Reproducible with: 2018.2.0b4, 2018.2.0f1, 2018.3.0a4
Not reproducible with: 2018.2.0a4, 2018.2.0b3
This issue is primarily a problem with Windows, DXGI, and/or the graphics driver, in which Windows fails (refuses) to set the requested ExclusiveFullScreen resolution in some situations. That is, it's ultimately a bug in the OS and not something Unity (or any other DirectX application) can fix.
The problem seems to occur in multiple monitor configurations with the Desktop "extended" across the displays (at least I didn't encounter the problem with single display configurations), in which the app attempts to set ExclusiveFullscreen on the primary display with a significantly lower resolution than the secondary display.
For example: given a dual monitor configuration with both displays set at a native resolution of 2560x1440, attempting to set the primary display to Exclusive 640x480 will always fail with the display reverting back to its native resolution and non-exclusive Fullscreen mode. However, this same operation on the secondary display will (eventually) succeed. Furthermore, setting ExclusiveFullscreen on either display with a mid-range resolution of 1600x900 with also succeed.
So, unfortunately Unity has to handle this potential failure case by validating the actual display resolution with the original change request, and if the mode change failed, i.e. we didn't get the display mode we wanted, then the runtime must update the internal state to match, otherwise a lot of bad things will happen. Of course, this change isn't directly communicated to the scripts, meaning the values in the UI won't match the actual state, as is the case with this bug.
Given this problem, there is a "partial fix" that helps improve the situation In many cases: the original display mode change may fail but a second attempt will often succeed (go figure). So after the script sets ExclusiveFullscreen mode, Unity will first verify the change was successful and if not immediately try to set the display mode again. If the second attempt fails, it means this mode cannot be used and the system must revert back to the active display mode.
ExclusiveFullscreen is very problematic, probably why it's not supported in UWP and MacOS. So please consider the following if you intend to use it:
- Scripts should perform their own validation after a mode change to verify the selected mode was actually set and update the UI accordingly. Note that it will take up to 2 frames for this entire operation to complete.
- Unless you have good reason, remove the "ulta-low" resolutions from the selection list: 640x480, 800x600, etc.
- Prefer display modes that best match the monitor's native aspect ratio, since it could be that setting a 4:3 resolution on the primary display is more likely to fail if the second display is currently set to a 16:9 resolution.
All about bugs
View bugs we have successfully reproduced, and vote for the bugs you want to see fixed most urgently.
- [TextMesh Pro] Using Ellipsis overflow causes some Emojis to turn into a Square when truncated
- Editor: Assembly icons are not shown correctly.
- [VR]Editor Crashes when exiting the Play Mode if VR support is enabled and a Particle System is emitting mesh instances
- Object with ISerializationCallbackReceiver Interface receives Serialization Callback when it has a private access level
- AssetModificationProcessor.OnWillCreateAsset Callbacks are inconsistent with different Assets