유니티

[유니티 최적화] UI 최적화 (Drawcall 줄이기(Atlas 활용) , UI 옵션 조정)

yamaeking 2025. 4. 23. 14:32

alert("Hello World!");

개발 중인 게임이 안드로이드 빌드하였을 때 너~무 뻑뻑한 느낌이 들어서 최근에 최적화에 대해 이것 저것 공부하였다. 그 중 도움 될 만한 내용들을 정리해보고자 아래와 같이 공유해 본다.

 

*참고로 버전은 유니티 최신 버젼, 6000 버전임.

 

1. Profiling 으로 어떤 것이 부하를 많이 일으키고 있나 확인.


https://yamaeking.tistory.com/105

 

[유니티 최적화] Profiling (빌드 이후 메모리 사용량 등 확인 하기.)

에디터에서는 무리 없이 잘 작동되는 거 같은데, 안드로이드로 빌드만 하면 뭔가 버벅거리는 느낌이 나서 이걸 어떻게 찾아서 분석해야 하나 싶었다. 다행히 유니티에서는 profiling 기능을 제공

yamaeking.tistory.com

 >> 기본적으로 Profiling 을 통해 메인 부하가 어떤 것인지 확인하여야 된다. 어떻게 확인하는 지는 위 글에 남겼으니 참고 바란다. (이건 UI랑 관계 없이 기본이다.)

 

 

 

 

2. Drawcall 확인 및 Sprite Atlas로 Drawcall 줄이기.


 >> PC에서는 Drawcall이 몇 백개 되어도 크게 상관이 없다고 한다. (상관이 없다라기보다는 PC 성능이 상대적으로 훨씬 좋으니 성능으로 부하를 압살하는 느낌ㅇㅇ;)

>> 근데 모바일에서는 Drawcall이 50개 이하인 것이 이상적이라고 한다. 왜냐? 일반적으로 모바일 기기는 PC보다 성능이 꾸지기 때문이다. 그러면 본인이 만들고 있는 게임이 Drawcall이 얼마인지 확인해 보자. 이건 크게 두 가지 방법으로 확인할 수 있는데,

 

 1) Window -> Analysis -> Profiler 

 > 확인하고 싶은 특정 시점을 클릭하여, 왼쪽에 보이는 Rendering 을 클릭해 보면 아래에 보이는 것 같이 Draw Calls로 확인할 수 있다. 본인 게임의 인벤토리를 열었을 때 생기는 Drawcall인데, 실제적으로 아틀라스 작업을 하기 전이어서 모든 sprite를 하나 하나 drawcall하여 그리고 있었던 상황이다.

 

2) Window -> Analysis -> FrameDebugger

 

 

> 사실 처음 profiler에서도 확인할 수 있기는 한데, 아무튼 확인하고 싶은 시점에서 Frame Debugger를 실행하고 Enable 버튼을 누르면 아래와 같은 화면이 나온다.

> 이건 상점 열었을 때 화면인데, Drawcall이 54개이다. 오른쪽에 Output 등을 눌러보면 이 Drawcall이 어떤 것을 그리고 있는지 나옴.

 

 

스프라이트 아틀라스로 Drawcall 줄이기.

 

--> Drawcall을 확인하였고, Drawcall이 많다라고 한다면 Sprite Altas를 이용해야 한다. 아틀라스 사용법은 아래 글을 참고하면 되겠고, 

https://yamaeking.tistory.com/106

 

[유니티6] 스프라이트 아틀라스(Sprite Atlas) 사용법 및 주의점 (유니티 최적화)

printf("Hello world!\n"); 보통 2D 게임을 만들 때, 렌더링 시 어떤 스프라이트를 참고하여 Draw 하게 되는데 이때 Drawcall이라는 것을 한 번 호출하게 된다. 근데 예를 들어 아래와 같이 그릴 것들이 많아

yamaeking.tistory.com

본인은 Sprite Atlas를 통해 아래와 같이 인벤토리 Drawcall을 98개에서 -> 44개로 줄였다. 홀리몰리; 

 

 > 거의 반타작 난건데, 어떻게 이렇게 줄었지? 싶어서 Debugger 를 구경해봤다. (굳이 배경화면까지 노출할 필요는 없을 거 같아서 배경은 대충 그림판으로 지움;)

 

> 눈 여겨 볼 만한 것이, Drawcall 한 번으로 아이템들을 싹 그렸다. Atlas 적용하기 전에는 저기 보이는 아이템 Sprite들을 한땀 한땀 Drawcall로 불러와서 그렸었는데, 이걸 Drawcall 한 번으로 다 그린 것이다. 아틀라스 짱짱맨이다 이것이다. 두 번 써라.

 (*다만 Sprite 들이 서로 다른 아틀라스에 있거나, 같은 아틀라스에 있더라도 아틀라스에서 서로 다른 페이지에 있으면 drawcall이 각각 호출된다. )

(스프라이트가 서로 다른 페이지에 있으면 각각의 drawcall이 호출.)

 

 * 그래서 권장하는 방법은 Sprite들을 용도 별로 잘 구별하여서 최대한 한 곳에 비슷한 것들을 낑겨 넣는 것이다.

본인은 아이템 이미지 같은 경우에 아래에서 처럼 하나의 atlas에 낑겨 넣어놨기 때문에 위에서 하나의 Drawcall에서 모든 아이템 이미지 그리는 것이 가능했던 것이다.

 

-> 이외에 SpriteAtlas 사용시에 주의사항(type을 single로 해야 하는 등)도 있는데, 그건 위에 걸어둔 링크를 참고하라.

 

 

 

3. 이벤트 대상(클릭 등)이 아닌 UI는 raycast를 꺼라.


>  UI를 만들다 보면, 버튼을 만들더라도 버튼 하나만 딸랑 만드는 게 아니고 이쁘게 꾸민다고 Frame을 씌우기도 하고, 표시할 내용이 있으면 Text를 붙이는 등 여러 잡스런(??) 요소들을 많이 갖다 붙일 것이다.

이런 식으로 잡스럽게 다다다.

 

 > 꾸미는 건 사실 문제가 안 되고(당연히 UI니까 보기 좋아야 함ㅇㅇ;), 클릭이나 드래그 등 이벤트 대상이 아닌 경우에는 아래와 같이 Raycast Target을 끄는 것이 성능상 좋다. (TMP_Text 를 쓸 때에는, Rich Text 옵션이 필요 없다하면 끄라고 한다. 이것도 은근 성능을 잡아 먹는다 함.)

 

RayCast를 꺼야하는 이유.

 

Raycast Target이란?

Unity에서 Image, Text, RawImage 등 UI 컴포넌트에는 기본적으로 Raycast Target 옵션이 있다.
이걸 켜두면 해당 UI 오브젝트는 터치나 클릭과 같은 사용자 입력 이벤트의 대상이 될 수 있게 된다. 즉, 이벤트 시스템이 해당 UI 위에 Ray를 쏴서 맞았는지 계산한다.

 

 

Raycast Target이 켜져 있는 UI는 전부 이벤트 처리 대상으로 포함된다.
→ 마우스나 터치 입력이 들어올 때마다 → 캔버스의 모든 UI 요소를 순회하면서 "맞았는가?"를 검사한다.

  • 투명한 Image 컴포넌트
  • 읽기 전용 Text UI
  • 장식용 프레임, 배경 요소 등
     클릭할 일 없는데도 전부 검사 대상

 

 **** 즉 쓸 데 없이 Raycast Target 옵션을 켜둔 UI들이 많다면 '이벤트 처리 비용' 이 증가한다 이 말이다. 유남생? 그러니 쓸 데 없는 raycast는 꺼두자.

 

 

 

 

4. 텍스쳐 크기 줄이기


 

 > 말 그대로 작게 표시되는 Sprite들은 텍스쳐 크기를 줄이라는 것이다. Sprite 클릭하고 오른 쪽 위 Inspector 창에서 밑으로 내리면 텍스쳐 크기 조절할 수 있는데, (빌드 환경에 맞게 세팅가능.) 아이콘 등 굳이 화면에서 크지 않은 sprite들은 크기를 적절히 조절해준다. (대충 128~256? upto you)  

 (보통 에셋 스토어 같은 데서 sprite들 줏어(??)오거나 사오면 이미지 크기가 큰(1024, 2048) 경우가 왕왕 있는데, 배경 화면 같은 경우에는 그렇게 써도 되겠지만 아이콘 같은 것들은 굳이 그대로 쓸 필요가 없다.)

 

줄임으로써 생겨나는 이점은 아래와 같으니 참고 ㄱㄱ


1. 메모리 사용량 감소 (RAM, VRAM)

  • 텍스처 크기가 작을수록 게임 실행 시 **그래픽 메모리(VRAM)**와 일반 메모리(RAM) 점유가 줄어듦.
  • 예를 들어, 512x512보다 128x128짜리 텍스처는 용량이 16분의 1.
  • 특히 모바일 기기/저사양 PC는 VRAM이 적기 때문에, 텍스처가 크면 바로 메모리 부족(Out of Memory) 오류가 발생할 수 있다.

2. 로딩 속도 개선

  • 텍스처가 작을수록 디스크에서 메모리로 읽어들이는 시간이 짧다.
  • 씬 전환, 리소스 로딩 등에서 로딩 속도 단축 → 사용자 경험 개선.

3. GPU 성능 최적화

  • GPU는 화면에 보이는 텍스처를 타일 단위로 캐싱하고 처리함.
  • 텍스처가 클수록 GPU가 한 번에 처리해야 하는 데이터가 많아져서 버스 대역폭, 캐시 효율 저하가 발생.
  • 작은 텍스처는 GPU texture cache miss를 줄여주고, 더 많은 텍스처를 동시에 유지할 수 있다.

4.패키지 용량 감소 (앱 크기)

  • 텍스처가 작으면 apk/ipa 파일 용량도 감소.
  • 배포 및 다운로드/설치 속도 향상, 사용자의 저장공간 부담 감소.

5. 모바일 발열/배터리 관리

  • 작은 텍스처는 메모리 접근 및 데이터 이동량이 줄어들어, GPU/CPU 발열과 배터리 소모를 줄이는 데도 도움.

 

 

 

5. null 이미지는 Sprite Atlas 그룹에 묶여 있는 이미지로 교체.


> 위에 보는것처럼, UI를 만들 때 다양한 이유로 Image 의 Source Image에 null을 넣는 경우가 많을 것이다.

(Blocker나 그냥 Frame 등등)

 

>  찾아 보니까 null Image 도 Drawcall을 발생시킨다고 한다. 그러니 null image 를 써야 할 곳이 있다면, 가급적 주변 Sprite와 같은 Atlas에 있는 Sprite 를 사용하도록 하자.

 

 

 

 

번외 : 빌드할 때 Development Build가 아닌 Release Mode로 하기


 

> 온갖 것들을 다 시도해봤는데 왜 Profiler 등으로 확인 했을 때 Frame이 낮게 나오지? 한다면 Development Build 체크를 해제 하고 Release mode 로 build 해보라.

 Development mode 일 때는 말 그대로 개발 모드로 빌드하는 것이라 디버깅 및 모니터링을 위한 부가 코드와 로그, 오버헤드가 실제 게임 성능을 방해한다. 그리고 Release Mode 일 때가 코드 최적화가 좀 더 공격적으로 들어간다.

 

> 내가 만드는 게임은 2D 게임이고 뭐도 없는 로비 화면이 자꾸 30FPS 정도만 나오길래 왜 이럴까 의아했다. 근데 알고 보니 Development mode 여서 그랬던 것,, 저걸 해제 하고 실행하니 60PFS 가 나왔다. (TargetFrame을 60으로 설정해 둬서 이 정도로 나옴.)

 

 > 어차피 게임 출시할 때는 Release Mode 로 빌드하게 되니, Development Mode에서 Frame 이 너무 안 나온다고 머리 싸매지 말고, 최적화는 최적화대로 진행하되 실제 출시했을 때를 가정하고 frame 등을 체크할 때는 Development Build 체크 해제 하고 보라.