I’ve been able to fix this by checking if newResolution.width < 640 and setting to 1920 x 1080 if so. So it’s not a bug with SetResolution. Could it be that Screen.resolutions wrongly reports 1x1 resolutions in some cases? The fact that this is happening only on ~1% of players’ machines makes me think it’s not a bug in my code but rather something between Unity and some specific hardware setup.
In any case, here’s the code I’m using to get the available resolutions, maybe I’m messing up somewhere that I’m not aware of:
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using Sirenix.OdinInspector;
using System.Linq;
public class ResolutionDropdownPopulator : MonoBehaviour
{
public TMP_Dropdown resolutionDropdown;
private List<Resolution> resolutions;
void Awake()
{
PopulateDropdown();
}
[Button]
public void PopulateDropdown()
{
resolutions = new List<Resolution>(Screen.resolutions);
// Fall back list if resolutions.Count is 1 or smaller. Just populate it with popular 16:9 options
bool fallbackListUsed = false;
if (resolutions.Count <= 1)
{
Debug.Log("Less than 2 resolutions reported by Screen.resolutions. Generating Fallback Resolutions List");
fallbackListUsed = true;
// Adding common 16:9 resolutions as fallback, including more low-res options
resolutions.Add(new Resolution { width = 1920, height = 1080 }); // Full HD
resolutions.Add(new Resolution { width = 1600, height = 900 }); // HD+
resolutions.Add(new Resolution { width = 1366, height = 768 }); // Common laptop screen
resolutions.Add(new Resolution { width = 1280, height = 720 }); // HD
resolutions.Add(new Resolution { width = 1024, height = 576 }); // Lower HD
resolutions.Add(new Resolution { width = 960, height = 540 }); // qHD
resolutions.Add(new Resolution { width = 854, height = 480 }); // FWVGA
resolutions.Add(new Resolution { width = 800, height = 450 }); // WVGA
resolutions.Add(new Resolution { width = 720, height = 405 }); //
resolutions.Add(new Resolution { width = 640, height = 360 }); // Standard Definition
resolutions.Add(new Resolution { width = 2560, height = 1440 }); // QHD
resolutions.Add(new Resolution { width = 3840, height = 2160 }); // 4K
}
// Always have a 1920 x 1080 option in the list
if (!resolutions.Any(res => res.width == 1920 && res.height == 1080))
resolutions.Add(new Resolution { width = 1920, height = 1080, refreshRateRatio = resolutions[0].refreshRateRatio });
// Add Macbook 16:9 for trailer recording.
//resolutions.Add(new Resolution { width = 3456, height = 1944, refreshRateRatio = resolutions[0].refreshRateRatio });
// Remove Refreshrate duplicates
resolutions = resolutions.GroupBy(res => new { res.width, res.height })
.Select(group => group.First())
.ToList();
// Order list by descending resolutions
resolutions = resolutions.OrderByDescending(res => res.width).ThenByDescending(res => res.height).ToList();
List<string> options = new List<string>();
int currentResolutionIndex = 0;
for (int i = 0; i < resolutions.Count; i++)
{
string option = resolutions[i].width + " x " + resolutions[i].height;
options.Add(option);
if (!fallbackListUsed)
{
// If not using fall back list, set current resolution to match Screen.currentResolution
if (resolutions[i].width == Screen.currentResolution.width &&
resolutions[i].height == Screen.currentResolution.height)
{
currentResolutionIndex = i;
}
}
else
{
// If using fallback List, set currentResolution to 1920 x 1080 to avoid fuckups.
if (resolutions[i].width == 1920)
{
currentResolutionIndex = i;
}
}
}
resolutionDropdown.ClearOptions();
resolutionDropdown.AddOptions(options);
resolutionDropdown.SetValueWithoutNotify(currentResolutionIndex);
resolutionDropdown.RefreshShownValue();
}
}
This is the code I’m using to then apply the resolution:
public void SetResolution(TMP_Dropdown dropdown)
{
if (dropdown.options.Count <= 0)
{
Debug.LogError("No Resolution Options.", dropdown.gameObject);
return;
}
previousResolution = Screen.currentResolution;
resolutionConfirmDialog.StartCountdown();
string selectedOption = dropdown.options[dropdown.value].text;
string[] dimensions = selectedOption.Split('x');
if (dimensions.Length == 2)
{
if (int.TryParse(dimensions[0].Trim(), out int width) && int.TryParse(dimensions[1].Trim(), out int height))
{
//Screen.SetResolution(width, height, Screen.fullScreen);
Settings.CurrentSettings.resolution = new Resolution { width = width, height = height };
Settings.CurrentSettings.Apply();
Debug.Log($"Setting Resolution to: {width} x {height}. Selected Option from dropdown = {selectedOption}, dimensions = {dimensions[0]} x {dimensions[1]}. New Screen Resolution = {Screen.currentResolution}.");
}
else
{
Debug.LogError("Failed to parse resolution dimensions from dropdown value.");
}
}
else
{
Debug.LogError("Invalid resolution format in dropdown value.");
}
}
The Settings.CurrentSettings.Apply() method simply calls Screen.SetResolution(newResolution.width, newResolution.height, Settings.CurrentSettings.fullscreen);