티스토리 뷰
소스코드 출처
다양한 화면 비율의 문제와 래터박스
다양한 화면 비율에 맞춰 게임을 각각 개발하는 것은 매우 어렵고도 힘든 일입니다.
하지만 화면 비율을 무시하고 게임을 개발하게 된다면 게임 플레이어들은 개발자가 의도하지 않은 상황에 처할 수 있으며 극단적으로는 게임을 플레이할 수 없게 되기도 합니다.
이러한 문제를 해결하기 위한 방법중 간단한 방법으로 래터박스가 있습니다. 대표적인 몇 가지 화면 비율로 개발한 뒤 그 외의 화면 비율에는 래터박스를 채워 화면 비율을 맞추는 방법입니다.
유니티에서 래터박스를 만드는 방법
유니티의 카메라 컴포넌트를 살펴보면 Viewport Rect라는 속성이 있습니다. Viewport Rect는 유니티의 가상 카메라가 비추는 영역을 실제 화면의 어느 위치에 보여줄지 정할 수 있는데 이를 이용하여 래터박스를 생성합니다. 예를 들면 게임의 가로 화면 비율보다 화면의 가로 비율이 높다면 화면의 가로 일정 영역을 피해 게임 화면을 보여줄 수 있습니다.
화면 비율 계산
가로의 경우
실제 화면과 원하는 화면의 세로 비율을 1로 놓았을 때 가로의 비를 구합니다.
(원하는 화면의 가로 비 나누기 실제 화면 가로 비) 를 통해 실제 화면에서 원하는 화면의 비율을 구합니다.
이 비율은 Viewport Rect 의 W에 들어갑니다.
이제 원하는 화면만큼만 사용할 수 있게 되었지만 화면의 위치가 중앙이 아니라는 문제가 남았습니다. 이 문제는 Viewport Rect의 X 값을 조절하여 해결할 수 있습니다.
X 값은 원하는 화면의 비율에서 1을 뺀 값 나누기 2 를 한 값 입니다.
원하는 화면의 비율에서 1을 빼게 되면 원하지 않는 화면의 비율입니다. 이 비율의 반 값 만큼 X 축으로 이동하면 정확히 중앙에 위차하게 됩니다.
예) 실제 화면 비율 3:2 -> 1.5:1 ,원하는 비율 9:16 -> 0.5625:1 ,
0.5625/1.5 = 0.375 실제 화면에서 원하는 화면이 차지하는 비율
세로의 경우도 위와 약간의 순서만 다르고 비슷합니다.
소스코드
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 | using UnityEngine; public class AspectUtility : MonoBehaviour { public int x; public int y; static float wantedAspectRatio; static Camera cam; static Camera backgroundCam; void Awake() { cam = GetComponent<Camera>(); if (!cam) { cam = Camera.main; } if (!cam) { Debug.LogError("No camera available"); return; } wantedAspectRatio = (float)x / y; SetCamera(); } public static void SetCamera() { float currentAspectRatio = (float)Screen.width / Screen.height; // If the current aspect ratio is already approximately equal to the desired aspect ratio, // use a full-screen Rect (in case it was set to something else previously) if ((int)(currentAspectRatio * 100) / 100.0f == (int)(wantedAspectRatio * 100) / 100.0f) { cam.rect = new Rect(0.0f, 0.0f, 1.0f, 1.0f); if (backgroundCam) { Destroy(backgroundCam.gameObject); } return; } // Pillarbox if (currentAspectRatio > wantedAspectRatio) { float inset = 1.0f - wantedAspectRatio / currentAspectRatio; //Debug.Log(new Rect(inset / 2, 0.0f, 1.0f - inset, 1.0f)); cam.rect = new Rect(inset / 2, 0.0f, 1.0f - inset, 1.0f); } // Letterbox else { float inset = 1.0f - currentAspectRatio / wantedAspectRatio; cam.rect = new Rect(0.0f, inset / 2, 1.0f, 1.0f - inset); } if (!backgroundCam) { // Make a new camera behind the normal camera which displays black; otherwise the unused space is undefined backgroundCam = new GameObject("BackgroundCam", typeof(Camera)).GetComponent<Camera>(); backgroundCam.depth = int.MinValue; backgroundCam.clearFlags = CameraClearFlags.SolidColor; backgroundCam.backgroundColor = Color.black; backgroundCam.cullingMask = 0; } } public static int screenHeight { get { return (int)(Screen.height * cam.rect.height); } } public static int screenWidth { get { return (int)(Screen.width * cam.rect.width); } } public static int xOffset { get { return (int)(Screen.width * cam.rect.x); } } public static int yOffset { get { return (int)(Screen.height * cam.rect.y); } } public static Rect screenRect { get { return new Rect(cam.rect.x * Screen.width, cam.rect.y * Screen.height, cam.rect.width * Screen.width, cam.rect.height * Screen.height); } } public static Vector3 mousePosition { get { Vector3 mousePos = Input.mousePosition; mousePos.y -= (int)(cam.rect.y * Screen.height); mousePos.x -= (int)(cam.rect.x * Screen.width); return mousePos; } } public static Vector2 guiMousePosition { get { Vector2 mousePos = Event.current.mousePosition; mousePos.y = Mathf.Clamp(mousePos.y, cam.rect.y * Screen.height, cam.rect.y * Screen.height + cam.rect.height * Screen.height); mousePos.x = Mathf.Clamp(mousePos.x, cam.rect.x * Screen.width, cam.rect.x * Screen.width + cam.rect.width * Screen.width); return mousePos; } } } | cs |
'Unity > Study' 카테고리의 다른 글
[Unity] Coroutine 의 yield return 뒤 함수 확장 (0) | 2018.05.31 |
---|---|
[Unity] 키 입력 받는 방법 세 가지 비교 (3) | 2018.05.28 |
visual studio 코드 스니핏 (0) | 2018.01.24 |
[Unity] sin, cos 함수를 이용한 원 운동 (0) | 2018.01.19 |
[Unity] Sin 함수를 통한 반복 운동 (0) | 2018.01.18 |