일지
유니티 화면 비율 고정 처리...10
niamdank
2021. 10. 5. 18:43
화면 비율 고정 처리 동작 안 하는 경우 확인
비율 처리가 동작하지 않는 경우에 대한 처리를 확인하기 위해 코드를 조금 정리해서 상태에 따라 값을 출력하도록 했다.
ResolutionController.cs
using System;
using System.Collections;
using System.Runtime.InteropServices;
using UnityEngine;
using UnityEngine.UI;
public class ResolutionController : MonoBehaviour
{
public float AspectX { get; set; } = 16;
public float AspectY { get; set; } = 9;
public Text m_debugText;
#region ENUMERATIONS
private enum Cursors
{
IDC_ARROW = 32512,
IDC_SIZENESW = 32643,
IDC_SIZENS = 32645,
IDC_SIZENWSE = 32642,
IDC_SIZEWE = 32644,
}
private enum UpdateState
{
Waiting,
Changing,
Updating,
}
#endregion
#region WINAPI_DLL
[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
public Int32 x;
public Int32 y;
}
private const int VK_LBUTTON = 0x01;
private const ushort KEY_HOLD = 0x8000;
[DllImport("user32.dll")]
private static extern IntPtr GetCursor();
[DllImport("user32.dll")]
private static extern IntPtr LoadCursor(IntPtr hInstance, int lpCursorName);
[DllImport("user32.dll")]
private static extern ushort GetAsyncKeyState(ushort vKey);
#endregion
#region WINAPI_VARIABLES
private IntPtr CursorNESW { get; set; }
private IntPtr CursorNS { get; set; }
private IntPtr CursorNWSE { get; set; }
private IntPtr CursorWE { get; set; }
#endregion
private float m_aspectRatio;
private int m_screenSizeX;
private int m_screenSizeY;
private UpdateState m_updateState;
private void Start()
{
m_aspectRatio = AspectX / AspectY;
m_screenSizeX = Screen.width;
m_screenSizeY = Screen.height;
Initialize();
}
private void Initialize()
{
CursorNESW = LoadCursor(IntPtr.Zero, (int)Cursors.IDC_SIZENESW);
CursorNS = LoadCursor(IntPtr.Zero, (int)Cursors.IDC_SIZENS);
CursorNWSE = LoadCursor(IntPtr.Zero, (int)Cursors.IDC_SIZENWSE);
CursorWE = LoadCursor(IntPtr.Zero, (int)Cursors.IDC_SIZEWE);
m_updateState = UpdateState.Waiting;
m_debugText.text = $"Update State : {m_updateState}";
}
private void Update()
{
IntPtr hCursor = GetCursor();
if (m_updateState == UpdateState.Waiting && IsChanging(hCursor) && IsMouseButtonClicked())
{
m_updateState = UpdateState.Changing;
m_debugText.text = $"Update State : {m_updateState}";
}
else if(m_updateState == UpdateState.Changing && !IsMouseButtonClicked())
{
StartCoroutine(SetFixedResolution());
}
}
private IEnumerator SetFixedResolution()
{
m_updateState = UpdateState.Updating;
m_debugText.text = $"Update State : {m_updateState}";
int newScreenSizeX = Screen.width;
int newScreenSizeY = Screen.height;
if (newScreenSizeX != m_screenSizeX && newScreenSizeY != m_screenSizeY)
{
if (Mathf.Abs(newScreenSizeX - m_screenSizeX) > Mathf.Abs(newScreenSizeY - m_screenSizeY))
{
newScreenSizeY = Mathf.FloorToInt(newScreenSizeX / m_aspectRatio);
}
else
{
newScreenSizeX = Mathf.FloorToInt(newScreenSizeY * m_aspectRatio);
}
}
else if (newScreenSizeX != m_screenSizeX)
{
newScreenSizeY = Mathf.FloorToInt(newScreenSizeX / m_aspectRatio);
}
else
{
newScreenSizeX = Mathf.FloorToInt(newScreenSizeY * m_aspectRatio);
}
m_screenSizeX = newScreenSizeX;
m_screenSizeY = newScreenSizeY;
Screen.SetResolution(m_screenSizeX, m_screenSizeY, false);
yield return null;
m_updateState = UpdateState.Waiting;
m_debugText.text = $"Update State : {m_updateState}";
}
private bool IsChanging(IntPtr hCursor)
{
if (hCursor == CursorNESW) return true;
if (hCursor == CursorNS) return true;
if (hCursor == CursorNWSE) return true;
if (hCursor == CursorWE) return true;
return false;
}
private bool IsMouseButtonClicked()
{
return (GetAsyncKeyState(VK_LBUTTON) & KEY_HOLD) != 0;
}
}
빌드 후 실행 결과는 다음과 같다.

아마 변경 과정에 SetResolution이 씹히고 있는 게 아닐까 한다.
생각해 볼 수 있는 처리 방법으로는 변경 후 대기 시간을 조금 늘려주거나 확실히 변경될 수 있도록 여러 번 과정을 반복시키는 방법이 있을 것 같다.