사이즈를 유지하며 창 크기가 유지 될 수 있도록 하기
- 빌드 세팅에서
Resolution and Presentation
중 -
Fullscreen Mode
를Windowed
로 맞추면 창 모드로만 게임을 실행 할 수 있음
창모드
전체모드
문제점
- 창모드에서 사이즈를 줄이려하면 사이즈 조절에 잠겨 있는 문제가 발생
- Resizeable Window 를 체크하면 사이즈 조절은 가능해짐
- 너무 자유로워서 개발자가 의도한 사이즈만 제공할 수 없는 문제
- 빌드 옵션이 별도로 사이즈를 고정해서 조절할 수 있는 옵션이 없어 스크립트로 작성하여
- 엔진에서 사이즈를 확인하여 고정할 수 있도록 합니다.
스크립트
해상도 컨트롤러
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ResolutionController : MonoBehaviour
{
private const float TargetAspectRatio = 9f / 19.5f;
private Vector2 _lastScreenSize;
private Coroutine _resizeCoroutine;
private const float DebounceTime = 0.1f;
private void Start()
{
_lastScreenSize = new Vector2(Screen.width, Screen.height);
DontDestroyOnLoad(gameObject);
}
private void Update()
{
Vector2 screenSize = new Vector2(Screen.width,
Screen.height);
if (screenSize == _lastScreenSize) return;
if (_resizeCoroutine != null)
StopCoroutine(_resizeCoroutine);
_resizeCoroutine =
StartCoroutine(DebounceResize(screenSize));
_lastScreenSize = screenSize;
}
private IEnumerator DebounceResize(Vector2 newSize)
{
yield return new WaitForSeconds(DebounceTime);
float currentAspectRatio = newSize.x / newSize.y;
if (currentAspectRatio > TargetAspectRatio)
{
int newWidth = Mathf.RoundToInt(newSize.y *
TargetAspectRatio);
if (newWidth > 0 && newSize.y > 0)
{
Screen.SetResolution(newWidth, (int)newSize.y,
false);
}
}
else
{
int newHeight = Mathf.RoundToInt(newSize.x /
TargetAspectRatio);
if (newSize.x > 0 && newHeight > 0)
{
Screen.SetResolution((int)newSize.x, newHeight,
false);
}
}
}
}
디바운스 매커니즘 (Debounce Mechanism)
디바운스 메커니즘은 함수가 너무 자주 호출되지 않도록 하는 데 사용되는 프로그래밍 기술입니다.
이는 창 크기 조정, 검색 상자에 입력 또는 버튼 클릭 처리와 같이 짧은 기간 동안 이벤트가 빠르고 반복적으로 트리거될 수 있는 시나리오에서 특히 유용할 수 있습니다.
디바운싱의 목표는 함수가 실행되는 속도를 제한하여 성능을 향상하고 불필요한 처리를 줄이는 것입니다.
해당 스크립트에서 작동하는 디바운싱 방식
- 트리거 이벤트: 일반적으로 함수 실행을 트리거하는 이벤트가 발생합니다(예: 사용자가 창 크기를 조정함).
- 타이머 시작: 기능을 즉시 실행하는 대신 타이머가 시작됩니다. 타이머가 만료되기 전에 이벤트가 다시 트리거되면 타이머가 재설정됩니다.
- 함수 실행: 함수는 타이머가 만료되고 해당 시간 내에 새로운 트리거 이벤트가 발생하지 않은 후에만 실행됩니다.
코루틴을 중단하지 않고 지속적으로 함수를 호출하면 발생하는 문제
- 창 크기가 조정될 때마다 발생하는 이벤트가 있다고 가정해 보세요.
- 디바운싱이 없으면 창 크기가 조정되는 동안 레이아웃을 조정하는 함수가 여러 번 호출되어 잠재적으로 성능 문제가 발생할 수 있습니다.
- 디바운싱을 사용하면 사용자가 창 크기 조정을 중지한 후에 이 함수가 한 번만 호출되므로 호출 수가 줄어들고 성능이 향상됩니다.
비용 최적화
- 디바운스 메커니즘은 창 크기 조정 빈도를 제어하는 데 사용됩니다.
- 창 크기가 변경되면 종횡비를 즉시 조정하는 대신 코루틴이 지연(
debounceTime
)으로 시작됩니다. - 지연이 끝나기 전에 창 크기가 다시 변경되면 코루틴이 중지되고 다시 시작됩니다.
- 이렇게 하면 크기 조정이 잠시 동안 비활성화된 후에만 가로세로 비율 조정이 이루어지므로 잠재적으로 비용이 많이 드는
Screen.SetResolution
호출의 빈도가 줄어듭니다.
추가적인 문제점
최소 사이즈 설정
- 최소 사이즈를 지정하지 않아 한업이 작아지는 문제 발생
- 최소 사이즈는 빌드 사이즈의 50% 수준으로 설정
가로 세로 별도로 사이즈 조정이 가능해져 사이즈 변경 시 빈 공간 노출
- 이 부분은 코루틴을 호출 하는 과정에서 오는 딜레이 트러블
- 게임 화면 자체의 공간을 넓혀 백그라운드를 감추는 방법과 코루틴이 아닌 업데이트문에서 실시간으로 사이즈를 확인 하면 되지만, 2안의 경우 리소스 소모가 많아져 차라리 전체 사이즈에 대응이 가능한 백그라운드를 채우는 방법을 선택
- 다만, 이 문제는 PC 에서만 발생하기 때문에 사이즈를 조정할 수 없는 모바일 환경에서는 아무런 문제가 되지 않습니다.
최소사이즈 유지 스크립트 수정
// 최소 가로 / 세로 픽셀 사이즈
private const float MinWidth = 540f;
private const float MinHeight = 1170;
// 디바운스 (동시 변경 및 최소 사이즈 적용)
private IEnumerator DebounceResize(Vector2 newSize)
{
yield return new WaitForSeconds(DebounceTime);
bool isWidthResized = !Mathf.Approximately(newSize.x,
_lastScreenSize.x);
if (isWidthResized)
{
int newHeight = Mathf.RoundToInt(newSize.x /
TargetAspectRatio);
if(newHeight < MinHeight)
{
newHeight = (int)MinHeight;
newSize.x = Mathf.RoundToInt(newHeight *
TargetAspectRatio);
}
Screen.SetResolution((int)newSize.x, newHeight, false);
}
else
{
int newWidth = Mathf.RoundToInt(newSize.y *
TargetAspectRatio);
if(newWidth < MinWidth)
{
newWidth = (int)MinWidth;
newSize.y = Mathf.RoundToInt(newWidth /
TargetAspectRatio);
}
Screen.SetResolution(newWidth, (int)newSize.y, false);
}
}