ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 유니티 화면 비율 고정 처리...10
    일지 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이 씹히고 있는 게 아닐까 한다.

     

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

    댓글

Designed by Tistory.