구현 목표는 다음과 같습니다.
해상도란?
해상도란 화면에 렌더링되는 픽셀의 수를 말합니다.
Unity는 씬을 2D 이미지처럼 렌더링하며, 이때 설정된 해상도만큼의 픽셀을 사용해 화면을 그립니다.
예를 들어, 해상도를 1920 x 1080으로 설정하면 Unity는 총 2,073,600개의 픽셀을 사용해 화면을 구성합니다.
만약 사용자의 모니터가 3840 x 2160이라면, 이 렌더링 결과물은 늘어나서(스케일) 표시됩니다.
해상도 조절 핵심 단계
step 1. 모든 해상도 구하기
private Resolution[] resolutions; // 가능한 모든 해상도를 저장할 배열
...
void GetAllResolutions()
{
resolutions = Screen.resolutions;
}
Screen.resolutions
는 현재 데스크탑의 표현 가능한 모든 해상도를 반환합니다.
step 2. 드롭다운 선택지에 삽입하기
public TMP_Dropdown resolutionDropdown; // 해상도를 선택할 드롭다운
...
void SetUpDropdown()
{
resolutionDropdown.ClearOptions(); // 초기화
HashSet<string> options = new HashSet<string>();
int currentResolutionIndex = 0;
for (int i = 0; i < resolutions.Length; i++)
{
string option = resolutions[i].width + " X " + resolutions[i].height;
options.Add(option);
if (resolutions[i].width == Screen.currentResolution.width &&
resolutions[i].height == Screen.currentResolution.height)
{
currentResolutionIndex = i;
}
}
resolutionDropdown.AddOptions(new List<string>(options)); // 선택지 등록
resolutionDropdown.value = currentResolutionIndex; // 현재 해상도 표시
resolutionDropdown.RefreshShownValue(); // 값 갱신
}
이 단계에서는 해상도를 "1920 x 1080" 형식의 문자열로 변환하여 드롭다운의 항목으로 등록합니다.
또한 현재 화면 해상도에 해당하는 항목을 찾아 기본 선택값으로 지정합니다.
※ HashSet을 사용하는 이유는 중복된 해상도 항목이 표시되는 것을 방지하기 위함입니다.
step 3. 선택한 해상도 적용하기
public void SetResolution()
{
int resolutionIndex = resolutionDropdown.value;
Resolution resolution = resolutions[resolutionIndex];
Screen.SetResolution(resolution.width, resolution.height, Screen.fullScreen);
Debug.Log(Screen.width + " X " + Screen.height);
}
사용자가 선택한 드롭다운 인덱스를 기반으로 해상도 정보를 꺼내 Screen.SetResolution()을 호출합니다.
이렇게 하면 화면 해상도가 실시간으로 변경됩니다.
세 번째 인자인 Screen.fullScreen은 현재 전체 화면 모드 여부를 그대로 유지하기 위한 설정입니다.
Unity UI 요소인 Toggle을 사용하여 전체 화면 모드(FullScreen)와 창 모드(Windowed)를 전환하는 기능을 구현하겠습니다.
사용자는 두 개의 토글 중 하나를 선택하여 화면 모드를 변경할 수 있도록 구현했습니다.
step 1. 변수 및 열거형 선언
public Toggle fullToggle; // 전체 화면 모드
public Toggle windowToggle; // 창 모드
private Toggle activatedToggle; // 활성화된 모드
enum ScreenMode
{
Full,
Window
}
두 개의 토글을 UI에 배치하고, 코드에서 연결합니다. ScreenMode
열거형을 사용하여 현재 설정된 화면 모드를 명시적으로 표현할 수 있도록 했습니다.
step 2. 토글 초기화 및 이벤트 리스너 설정
void SetUpToggles()
{
// 리스너 추가하기
fullToggle.onValueChanged.AddListener(delegate { ToggleChanged(fullToggle); } );
windowToggle.onValueChanged.AddListener(delegate { ToggleChanged(windowToggle); });
// 시작 시 전체 화면 모드인 경우
if (Screen.fullScreen)
{
fullToggle.isOn = true;
activatedToggle = fullToggle;
}
// 시작 시 창 모드인 경우
else
{
windowToggle.isOn = true;
activatedToggle = windowToggle;
}
}
게임이 시작되었을 때 현재 화면 모드를 기준으로 토글 상태를 초기화합니다. 이후 토글이 변경되면 ToggleChanged()
함수가 호출되어 모드를 전환하게 됩니다.
step 3. 토글 변경 시 화면 모드 전환 처리
void ToggleChanged(Toggle changedToggle)
{
if(changedToggle.isOn)
{
activatedToggle = changedToggle;
// 전체 화면 모드 on
if (changedToggle == fullToggle)
{
// 창 모드 off
windowToggle.isOn = false;
screenMode = ScreenMode.Full;
}
// 창 모드 on
else
{
// 전체 화면 모드 off
fullToggle.isOn = false;
screenMode = ScreenMode.Window;
}
}
// changedToggle을 두 번 클릭한 경우 해제 방지하기
else
{
// 이미 활성화된 토글을 다시 클릭해서 끄려는 경우, 다시 켜기
if (activatedToggle == changedToggle)
{
activatedToggle.isOn = true;
}
}
SetScreenMode();
}
핵심 로직은 하나의 토글만 활성화되도록 하는 것입니다. 특히 이미 활성화된 토글을 다시 클릭했을 때 해제되지 않도록 강제로 유지하는 부분이 중요합니다.
( 저는 이 기능을 구현할 때 Toggle Group
이라는 걸 몰라서 이처럼 구현했습니다ㅜㅜ )
Step 4. 실제 해상도 적용하기
void SetScreenMode()
{
if (screenMode == ScreenMode.Full)
{
Screen.fullScreenMode = FullScreenMode.FullScreenWindow;
Screen.fullScreen = true;
}
else
{
Screen.fullScreenMode = FullScreenMode.Windowed;
Screen.fullScreen = false;
}
}
SetScreenMode()
함수는 설정된 screenMode
값을 기반으로 Unity의 화면 설정을 실제로 적용합니다. 반드시 ToggleChanged()
호출 후 실행되어야 합니다.
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
public class ResolutionContorller : MonoBehaviour
{
public TMP_Dropdown resolutionDropdown;
public Toggle fullToggle; // 전체 화면 모드
public Toggle windowToggle; // 창 모드
private Toggle activatedToggle; // 활성화된 모드
private Resolution[] resolutions;
enum ScreenMode
{
Full,
Window
}
ScreenMode screenMode;
private void Start()
{
SetUpDropdown();
SetUpToggles();
}
void GetAllResolutions()
{
resolutions = Screen.resolutions;
}
void SetUpDropdown()
{
resolutionDropdown.ClearOptions();
HashSet<string> options = new HashSet<string>();
int currentResolutionIndex = 0;
for (int i = 0; i < resolutions.Length; i++)
{
string option = resolutions[i].width + " X " + resolutions[i].height;
options.Add(option);
if (resolutions[i].width == Screen.currentResolution.width &&
resolutions[i].height == Screen.currentResolution.height)
{
currentResolutionIndex = i;
}
}
resolutionDropdown.AddOptions(new List<string>(options));
resolutionDropdown.value = currentResolutionIndex;
resolutionDropdown.RefreshShownValue();
}
public void SetResolution()
{
int resolutionIndex = resolutionDropdown.value;
Resolution resolution = resolutions[resolutionIndex];
Screen.SetResolution(resolution.width, resolution.height, Screen.fullScreen);
Debug.Log(Screen.width + " X " + Screen.height);
}
void SetUpToggles()
{
fullToggle.onValueChanged.AddListener(delegate { ToggleChanged(fullToggle); } );
windowToggle.onValueChanged.AddListener(delegate { ToggleChanged(windowToggle); });
if (Screen.fullScreen)
{
fullToggle.isOn = true;
activatedToggle = fullToggle;
}
else
{
windowToggle.isOn = true;
activatedToggle = windowToggle;
}
}
void ToggleChanged(Toggle changedToggle)
{
if(changedToggle.isOn)
{
activatedToggle = changedToggle;
if (changedToggle == fullToggle)
{
windowToggle.isOn = false;
screenMode = ScreenMode.Full;
}
else
{
fullToggle.isOn = false;
screenMode = ScreenMode.Window;
}
}
else
{
if (activatedToggle == changedToggle)
{
activatedToggle.isOn = true;
}
}
SetScreenMode();
}
public void SetScreenMode()
{
if(screenMode == ScreenMode.Full)
{
Screen.SetResolution(Screen.width, Screen.height, true);
}
else
{
Screen.SetResolution(Screen.width, Screen.height, false);
}
}
}
이상입니다.