Unity/UI

[Tip] 화면 해상도 & 가로 세로 비율 조정 01

몽실KUN 2020. 5. 17. 01:07

https://devsquare.tistory.com/13

 

[Tip] 화면 해상도 & 가로 세로 비율 조정 02

1편에 이은 후속이다. 1편에서 언급한 실험 결과인 셈. https://devsquare.tistory.com/11 [Tip] 화면 해상도 & 가로 세로 비율 조정 01 사실 Resolution과 AspectRatio를 고정하는 것은 그리 좋은 방법이 아니다...

devsquare.tistory.com

급하신 분은 결론부에 해당되는 2편을 보시는 걸 추천합니다.

 


 

 사실 Resolution과 AspectRatio를 고정하는 것은 그리 좋은 방법이 아니다. 가장 좋은 방법은 있는 그대로의 단말기 환경에 대응을 하는 것이다. 그럼에도 불구하고 몇몇 경우에 Resolution과 AspectRatio를 건들이는 것을 고려할 수 있다. 대개의 주된 원인은 아래와 같다.

 

 * 단말기의 화면 해상도가 단말기 성능 스펙에 비해 너무 큰 경우

 

 사실 PC게임도 해상도를 올리게 되면 GPU 연산 부하가 뛰어버린다. 문제는 일반적인 PC환경보다 높은 고해상도를 단말기 환경에서 가지고 있으니 발생하는 문제이다. 단말기의 구조적인 한계 때문에, 3D 그래픽의 성능은 PC보다 후달릴 수 밖에 없다. 같은 해상도여도 딸리는 판국에 해상도가 더 높으니 문제가 되는 셈. 다만 SetScreen을 조절한다면 Player 설정에서 Blit 모드를 항상 켜주어야 한다.

 

https://answers.unity.com/questions/1494067/screensetresolution-does-not-cover-all-screen.html

 

Screen.setresolution does not cover all screen - Unity Answers

 

answers.unity.com


경우에 따라서는 카메라의 AspectRatio를 조절해야 할 때도 있다. 소스코드는 아래를 참조했는데, 유니티에서 가급적이면 나눗셈 보단 곱셈 연산을 우선적으로 하라 그래서 일부 수식을 변경했다.

 

https://m.blog.naver.com/PostView.nhn?blogId=fnzlz&logNo=221069086916&proxyReferer=https:%2F%2Fwww.google.com%2F

 

[Unity_2017_08_08_01] 유니티 화면 종횡비, 화면비율, 해상도 고정하기

안드로이드의 최대 단점...아니지.. 이제 애플도 4:3 비율이아닌 16:9 16:10 비율도 여러가지 화면 비율이 ...

blog.naver.com

 

float targetWidthAspect = width * 0.01f;
float targetHeightAspect = height * 0.01f;

camera.aspect = targetWidthAspect / targetHeightAspect;

float widthRatio = Screen.width / targetWidthAspect;
float heightRatio = Screen.height / targetHeightAspect;

float heightAdd = ((100.0f * widthRatio / heightRatio) - 100.0f) * 0.005f;
float widthAdd = ((100.0f * heightRatio / widthRatio) - 100.0f) * 0.005f;

if (heightRatio > widthRatio)
{
    widthAdd = 0.0f;
}
else
{
    heightAdd = 0.0f;
}


camera.rect = new Rect(
    camera.rect.x + Mathf.Abs(widthAdd),
    camera.rect.y + Mathf.Abs(heightAdd),
    camera.rect.width + (widthAdd * 2),
    camera.rect.height + (heightAdd * 2)
    );

다만 이렇게 하면, 화면에 잔상이 남기 때문에 이를 지워주어야 한다.

private void OnPreCull()
    {
        Rect rect = camera.rect;
        Rect newRect = new Rect(0, 0, 1, 1);
        camera.rect = newRect;
        GL.Clear(true, true, Color.black);
        camera.rect = rect;
    }

유니티 에디터 상에서 Play를 통해 테스트 해보면 결과는 아래와 같다.

 

가장자리의 Red color는 디버깅을 위해 black 대신 그린 것

 


UI를 캔버스에 그릴 경우, 캔버스의 가로세로 비율 또한 조정을 해야 할 수 있다. 대게의 경우는 아래와 같은 방법으로 비율을 조정할 수 있다. 이때 조심해야할 것은 가급적이면 Render Mode를 Screen Space - Overlay를 선택하도록 하자. (너무 많은 블로그에서 아무런 생각도 없이 Screen Space - Camera를 추천한다.)

 

https://docs.unity3d.com/Packages/com.unity.ugui@1.0/manual/class-Canvas.html

 

Canvas | Unity UI | 1.0.0

Canvas The Canvas component represents the abstract space in which the UI is laid out and rendered. All UI elements must be children of a GameObject that has a Canvas component attached. When you create a UI element object from the menu (GameObject > Creat

docs.unity3d.com

스크린 스페이스 - 스크린 & 카메라

스크린 스페이스 - 카메라를 선택할 경우, 캔버스가 3D 오브젝트에 의해 가려질 수 있음을 명심하자.


문제는 위의 방법들을 대개 동시에 쓰기 때문에 발생한다.

 

1) 화면 해상도를 고정 해상도로 조절할 경우

  ▶Blit을 사용하지 않으면 화면 구석탱이에 조그맣게 그려진다.

  ▶Blit을 사용하면 실제 단말기 스크린 AspectRatio와 카메라 ViewPort Rect의 비율 차이 때문에 늘어짐이 발생한다.

2) 늘어짐 현상을 없애기 위해 위의 소스 코드를 쓴 경우

  ▶캔버스를 Screen Space - Overlay로 그리게 되면, UI가 공백에 그려지는 현상이 발생한다. (오잉!)

  ▶캔버스를 Screen Space - Camera로 그리게 되면 UI가 3D 오브젝트에 가려질 수 있다.


잠정적인 해결책 (실험 후 추후 추가 예정)

▶ 해상도 조정은 상수 뙇! 박지 말자.

    - 기존 스크린의 비율을 유지한 채 스케일링 
    - 미리 정해둔 Resolution 목록에서 AspectRatio의 차이가 가장 적은 것을 선택

 

▶기존 스크린의 비율을 유지한다면, 굳이 카메라의 ViewPort Rect를 건들 필요는 없다.

   다만, 스크린 비율을 유지하기 위해 무작정 해상도를 임의의 숫자로 스케일링 했을 시, 성능/품질 저하가 일어나지는 않는지 고민을 할 필요가 있다. 

 

▶미리 정해둔 Resolution 목록에서 AspectRatio의 차이가 가장 적은 것을 선택했다면, 경우에 따라서는 카메라 View Rect를 조정할 필요가 있다. (조정하면 스크린에 공백이 생기겠지만, 무작정 뙇 박는 것보다는 작게 생길 것이다.) 약간의 비율 차이는 ViewRect를 조정하지 않고, 화면 비율대로 늘려서 뿌리는게 나을 수도 있다.

 

▶Canvas는 가급적 Screen Space - Screen으로 하자.