무더운 여름입니다. 이게 날씨인가 싶지만 개발은 계속됩니다.
최근에 UI디자이너분의 요청에 따라 기존에 사용하던 SafeArea를 개량했는데
의외로 쓸만하다는 생각이 들어서 이렇게 기록해 놓습니다.
제 블로그에서도 소개드렸던 에셋스토어에서 무료로 배포하는 SafeArea 에셋의 스크립트를 개조한 것 입니다.
기존에 사용하던 SafeArea는 X축, Y축만 대응이 가능했다고 한다면, 이번에 개량하게된 버전은
Topn Bottom, Left, Right 4방향을 조절할 수 있게 되었습니다.
using UnityEngine;
public class SafeArea : MonoBehaviour
{
public enum SimDevice
{
None,
iPhoneX,
iPhoneXsMax,
Pixel3XL_LSL,
Pixel3XL_LSR
}
public static SimDevice Sim = SimDevice.None;
Rect[] NSA_iPhoneX = new Rect[]
{
new Rect (0f, 102f / 2436f, 1f, 2202f / 2436f), // Portrait
new Rect (132f / 2436f, 63f / 1125f, 2172f / 2436f, 1062f / 1125f) // Landscape
};
Rect[] NSA_iPhoneXsMax = new Rect[]
{
new Rect (0f, 102f / 2688f, 1f, 2454f / 2688f), // Portrait
new Rect (132f / 2688f, 63f / 1242f, 2424f / 2688f, 1179f / 1242f) // Landscape
};
Rect[] NSA_Pixel3XL_LSL = new Rect[]
{
new Rect (0f, 0f, 1f, 2789f / 2960f), // Portrait
new Rect (0f, 0f, 2789f / 2960f, 1f) // Landscape
};
Rect[] NSA_Pixel3XL_LSR = new Rect[]
{
new Rect (0f, 0f, 1f, 2789f / 2960f), // Portrait
new Rect (171f / 2960f, 0f, 2789f / 2960f, 1f) // Landscape
};
RectTransform Panel;
Rect LastSafeArea = new Rect (0, 0, 0, 0);
Vector2Int LastScreenSize = new Vector2Int (0, 0);
ScreenOrientation LastOrientation = ScreenOrientation.AutoRotation;
// 해상도 좌우 대응
[SerializeField] bool ConformLeft = true;
[SerializeField] bool ConformRight = true;
// 해상도 상하 대응
[SerializeField] bool ConformTop = true;
[SerializeField] bool ConformBottom = true;
[SerializeField] bool Logging = false;
void Awake ()
{
Panel = GetComponent<RectTransform> ();
if (Panel == null)
{
Debug.LogError ("Cannot apply safe area - no RectTransform found on " + name);
Destroy (gameObject);
}
Refresh ();
}
void Update ()
{
Refresh ();
}
void Refresh ()
{
Rect safeArea = GetSafeArea ();
if (safeArea != LastSafeArea
|| Screen.width != LastScreenSize.x
|| Screen.height != LastScreenSize.y
|| Screen.orientation != LastOrientation)
{
// Fix for having auto-rotate off and manually forcing a screen orientation.
// See https://forum.unity.com/threads/569236/#post-4473253 and https://forum.unity.com/threads/569236/page-2#post-5166467
LastScreenSize.x = Screen.width;
LastScreenSize.y = Screen.height;
LastOrientation = Screen.orientation;
ApplySafeArea (safeArea);
}
}
Rect GetSafeArea ()
{
Rect safeArea = Screen.safeArea;
if (Application.isEditor && Sim != SimDevice.None)
{
Rect nsa = new Rect (0, 0, Screen.width, Screen.height);
switch (Sim)
{
case SimDevice.iPhoneX:
if (Screen.height > Screen.width) // Portrait
nsa = NSA_iPhoneX[0];
else // Landscape
nsa = NSA_iPhoneX[1];
break;
case SimDevice.iPhoneXsMax:
if (Screen.height > Screen.width) // Portrait
nsa = NSA_iPhoneXsMax[0];
else // Landscape
nsa = NSA_iPhoneXsMax[1];
break;
case SimDevice.Pixel3XL_LSL:
if (Screen.height > Screen.width) // Portrait
nsa = NSA_Pixel3XL_LSL[0];
else // Landscape
nsa = NSA_Pixel3XL_LSL[1];
break;
case SimDevice.Pixel3XL_LSR:
if (Screen.height > Screen.width) // Portrait
nsa = NSA_Pixel3XL_LSR[0];
else // Landscape
nsa = NSA_Pixel3XL_LSR[1];
break;
default:
break;
}
safeArea = new Rect (Screen.width * nsa.x, Screen.height * nsa.y, Screen.width * nsa.width, Screen.height * nsa.height);
}
return safeArea;
}
void ApplySafeArea (Rect r)
{
LastSafeArea = r;
// Check for invalid screen startup state on some Samsung devices (see below)
if (Screen.width > 0 && Screen.height > 0)
{
// Convert safe area rectangle from absolute pixels to normalised anchor coordinates
Vector2 anchorMin = r.position;
Vector2 anchorMax = r.position + r.size;
if (!ConformRight) anchorMax.x = Screen.width;
if (!ConformLeft) anchorMin.x = 0;
if (!ConformTop) anchorMax.y = Screen.height;
if (!ConformBottom) anchorMin.y = 0;
anchorMin.x /= Screen.width;
anchorMin.y /= Screen.height;
anchorMax.x /= Screen.width;
anchorMax.y /= Screen.height;
// Fix for some Samsung devices (e.g. Note 10+, A71, S20) where Refresh gets called twice and the first time returns NaN anchor coordinates
// See https://forum.unity.com/threads/569236/page-2#post-6199352
if (anchorMin.x >= 0 && anchorMin.y >= 0 && anchorMax.x >= 0 && anchorMax.y >= 0)
{
Panel.anchorMin = anchorMin;
Panel.anchorMax = anchorMax;
}
}
if (Logging)
{
Debug.LogFormat ("New safe area applied to {0}: x={1}, y={2}, w={3}, h={4} on full extents w={5}, h={6}",
name, r.x, r.y, r.width, r.height, Screen.width, Screen.height);
}
}
}
반응형
'게임 개발 > Unity' 카테고리의 다른 글
[유니티 C#] 특정 텍스트 눌러서 팝업 띄우기 (2) | 2022.08.29 |
---|---|
[유니티 C#] MonoBehaviour를 상속 받아야하는 Singleton, 모노 싱글톤 (0) | 2021.08.29 |
[유니티 C#] UI Animation State 이름 중복 사용 (0) | 2021.07.11 |
[유니티 C#] PhotonNetwork 기본 콜백함수 찍먹하기 (1) | 2021.06.09 |
유니티 Admob mediation adapter 적용시 빌드에러 (0) | 2021.02.14 |