[Unity3D] 레터박스(Letter box)를 이용한 게임 화면 비율 조절 및 다중 카메라 사용




스마트폰 기기마다 해상도가 다르기 때문에 개발하는 입장에서도 상당히 난감하다는 얘기는 여기저기서 많이 들어왔다. 유니티 내에서 개발하는 것도 예외는 아닌데, 따라서 게임 화면을 일정한 비율로 유지하기 위한 방법을 몇가지 찾아봤다.


  1. 모든 해상도 별 게임 화면을 각각 구현 - 가장 정확하긴 하지만 가장 비효율적인 방법이다.
  2. Screen.SetResolution(width, height, bool)
  3. 레터 박스를 이용한 비율 조절
첫번째 방법은 당연히 시도조차 안 했고, 2번째 방법부터 알아보자.



1. Screen.SetResolution


public static void SetResolution(int width, int height, bool fullscreen, int preferredRefreshRate = 0);

너비와 높이의 해상도를 강제로 맞춰주는 함수이다. 게임이 시작될 때 실행되는 스크립트의 Awake나 Start 함수에 넣어주면 된다. 예를 들어 

Screen.SetResolution(720, 1280, true) 

라고 쓴다면 게임 화면이 강제로 full screen으로 720 * 1280으로 조절이 된다. 또는 특정한 비율, 예를 들어 9 : 16의 비율로 만들고 싶다면

Screen.SetResolution(width, (width / 9) * 16, true)

라고 적어주면 되겠다.
다만 SetResolution은 정말로 크기를 강제 조절하는 방법이라, 기기의 해상도 비율이 다르다면 자연스럽게 이미지가 길쭉해지거나 뚱뚱해지는 등 의도한대로 나오지 않고 깨지게 나올 수 있다.





2. Letter box 생성


게임을 하다보면 어떤 게임에서는 화면이 꽉 안차고 위 아래가 검은색 빈 공간으로 채워져 있는 것을 본 적이 있을 것이다. 이걸 레터 박스라고 하는데, 비율을 맞추기 위해 이미지를 왜곡하지 않고 아예 남은 공간을 검게 칠해버리는 것이다. 아래의 링크는 레터 박스를 생성하는 것을 참고한 것이다.




using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CameraResolution : MonoBehaviour
{
    void Start()
    {
        Camera camera = GetComponent<Camera>();
        Rect rect = camera.rect;
        float scaleheight = ((float)Screen.width / Screen.height) / ((float)9 / 16); // (가로 / 세로)
        float scalewidth = 1f / scaleheight;
        if (scaleheight < 1)
        {
            rect.height = scaleheight;
            rect.y = (1f - scaleheight) / 2f;
        }
        else
        {
            rect.width = scalewidth;
            rect.x = (1f - scalewidth) / 2f;
        }
        camera.rect = rect;
    }

    void OnPreCull() => GL.Clear(true, true, Color.black);


위의 코드는 게임 화면을 비추는 카메라에 스크립트를 부착시키면 된다. 위의 코드를 간략하게 설명하면, 화면의 너비와 높이를 일정 크기로 만들어서, 가로 모드인지 세로 모드인지 체크해주고 원하는 부분만 rect를 이용해서 비춰주고, 남은 부분은 OnPreCull로 검게 칠해버린다.
OnPreCull 함수는 아래의 링크에서 확인해보자.

https://docs.unity3d.com/kr/530/ScriptReference/MonoBehaviour.OnPreCull.html

Camera viewport rect는 카메라가 보이는 일정 범위를 정할 때 사용한다. 아래 링크를 보고 직접 한번 수치를 변경해서 어떤 기능인지 확인해보도록 하자.

https://docs.unity3d.com/kr/530/ScriptReference/Camera-rect.html


문제는 이 레터 박스를 만들었을 경우, UI와 인게임을 모두 하나의 카메라에서만 볼 수 있게 만들었다면, UI가 레터박스 밖으로 삐져 나가버리게 된다. 따라서 게임 카메라와 UI용 카메라를 따로 설정해주면 되겠다. UI용 카메라를 만들어보자.

1. Hierarchy -> 우클릭 -> camera로 카메라를 하나 더 만들어준다.



2. UI를 담은 Canvas의 Inspector 창에서
Render Mode : Screen Space - Camera로 바꾸고, Render Camera를 UI용으로 만든 카메라를 넣어준다. (카메라를 드래그해서 넣어줄 수 있다.)


3. UI 카메라의 depth를 -1, Main 카메라의 depth를 -2와 같이 깊이를 다르게 설정해주자. 깊이의 크기가 더 클수록 더 앞에 배치되는데, 즉 UI를 게임 화면 위에 배치할지, 게임 화면을 UI 위에 배치할지 차이다. 또한 Culling Mask를 Main 카메라는 Everything 혹은 default로, UI용 카메라는 UI로 바꿔주자.


혹시 위의 과정으로 한 카메라가 다른 카메라에 의해 덮혀서 안 보이게 된다면, Clear Flags를 바꿔보자. 각각 특정한 영역을 클리어해주는 역할을 하는데, 사실 정확히 뭘 클리어한다는지 알 수가 없다. (애당초 복잡한 UI 구조가 아니라 가릴 것도 없다..)



SetResolution이나 letter box를 이용한 방법 말고도 여러가지 방법이 있겠지만, 일단 본인이 의도한 대로 만들어졌으므로 딱히 다른 방법은 사용해보지 않았다. 혹시 다른 방법이 필요하다면 그 때가서 공부해보도록 하자.

댓글