NGUI 최적화의 핵심은 정적인 UI 들과 동적인 UI 들을 나누는 것이다. 나누는 기준은 패널이다. 예를 들어 다음과 같은 하이어라키를 생각해볼 수 있다.


Panel1

정적인 UI들

Panel2

동적인 UI들


이렇게 하는 이유는 UI 가 갱신될 때마다 UI 가 속한 패널의 지오매트리가 재구성되기 때문이다. 재구성 작업에 많은 양의 가비지가 발생한다. 여기서 주의해야할 점은 위치 이동같은 기본 변환은 '갱신' 에 포함되지 않는다는 것이다. 지오매트리가 변해야 하는 작업들, 예를 들어 SetActive, UILabel 의 text 변경 등이 갱신에 포함된다.


패널의 UI 들중 하나라도 갱신이 되면 패널의 모든 UI 들에 대한 지오매트리 재구성 작업이 수행된다. 따라서 제일 최악의 시나리오는 패널을 루트에 단 하나 만들어두는 것이다. 이러면 UI 의 변경은 곧 씬의 모든 UI 들의 갱신이라는 결과로 작용한다.


동적인 UI 들 역시 하나의 패널로 몰아넣는건 같은 이유로 피해야 한다. 그렇다고 해서 패널의 개수를 너무 많이 늘려서는 안되는데, 패널 단위로 드로우콜이 분리되기 때문에 렌더링 성능은 낮아진다. 따라서 성능 측정을 결과로 패널의 개수를 조절할 필요가 있다.

Posted by 카코데몬
,

게임의 리소스중 대부분은 텍스처이다. 따라서 텍스처 최적화는 게임 성능에 가장 큰 영향을 미친다.


아래는 텍스처 최적화에서 자주 논의되는 개념들을 나열한 것이다.


1. POT

POT 은 Power Of Two 의 약어로, 2의 거듭제곱을 말한다. 많은 하드웨어에서 2의 거듭제곱 크기인 텍스처만을 사용할 수 있다. 하지만 게임에서는 2의 거듭제곱이 아닌 텍스처들도 분명 존재하고, 유니티는 이를 사용할 수 있도록 하기 위해 내부적으로 작업을 수행한다. 이 작업은 원본 텍스처보다 큰 2의 거듭제곱 텍스처를 만들고 원본 크기만큼을 복사, uv 를 조절하는 작업이다. 따라서 메모리 비용이 증가한다. 원본 크기를 제외한 영역은 재활용할 수 없으므로 낭비이다. 따라서 가능한 2의 거듭제곱 텍스처를 사용해야만 한다.


2. Compression

1024 x 1024 크기의 32비트 텍스처는 4MB의 메모리를 차지한다. 안드로이드를 기준으로, 이 텍스처를 ETC1 포맷으로 압축하면 512KB 로 정확히 8배 감소한다. 메모리 최적화 면에서 압축이 가장 높은 효율을 보인다. 하지만 압축에는 다음과 같은 제약사항이 있다.

- 대부분 POT 크기의 텍스처만 지원한다

- iOS 에서 사용하는 압축 방식인 PVRTC 같이 정방 크기의 텍스처만 지원하는 경우도 있다

- 알파를 지원하지 않는 경우도 있다. ETC1 같은 포맷은 지원하지 않는다. 이는 아래의 Alpha Channel Split 을 참고한다

압축은 대부분의 하드웨어에서 지원하고 원본과 비교했을 때 품질 저하가 적기 때문에 적극 권장되는 방법이다.


3. Color Channel Bits 낮추기

압축 포맷을 사용하지 않을 경우 RGBA 32비트 혹은 RGB 24비트 포맷이 많이 사용된다. 둘의 차이는 알파 채널의 존재 여부이다. 각 채널당 8비트 를 할당한 포맷으로 품질면에서 제일 좋은 반면 메모리는 가장 많이 차지한다. 채널에 할당되는 비트수를 낮추는 것으로 품질은 떨어뜨리면서 차지하는 메모리를 낮출 수 있다. RGBA 32비트, RGB 24비트 모두 16비트로 낮출 수 있는데 RGBA 32비트의 경우 각 채널당 4비트, RGBA 24비트의 경우 R채널은 5비트, G채널은 6비트, B채널은 5비트가 된다. 그라데이션같이 색의 분포가 넓은 경우 비트를 낮췄을 때 디더링( Dithering ) 현상이 심하게 나타나는데 이를 줄이기 위해 포토샵 필터 등의 외부 툴이 필요한 경우도 있다.

비트를 낮추는 방법은 품질을 크게 떨어뜨리므로 주의해서 적용해야 한다.


4. Alpha Channel Split

알파 채널이 존재하는 텍스처를 알파를 지원하지 않는 방식으로 압축하고자 할 때 알파 채널을 분리하는 방법을 사용할 수 있다. UI 같이 대부분 알파 채널을 포함하는 곳에 자주 적용되는 방법이다. 개념은 간단한데 원본 텍스처에서 알파 채널을 분리하여 별도의 텍스처로 만들고 각각을 압축, 렌더링할 때 두 장의 텍스처를 읽어서 연산해주는 것이다. 텍스처가 두 장으로 늘어나서 비효율적일 것 같으나 RGBA 32비트 텍스처 기준으로 여전히 4배 적은 크기를 차지한다. 유니티4 까지는 직접 쉐이더를 구현해야 하고 유니티5 부터는 텍스처 타입이 Legacy GUI 혹은 Sprite 인 경우에 아래처럼 지원해준다.



5. Max Size

2048 크기를 1024로, 1024크기를 512로 낮추는 것처럼 텍스처 크기를 한 단계 내리는 것으로 메모리 크기를 4배 줄일 수 있다.


6. Mipmap

밉맵은 더 적은 bandwidth 로 텍스처를 렌더링할 수 있도록 해서 렌더링 성능과 품질을 높여주는 반면 원본 텍스처가 차지하는 메모리보다 약 33% 증가한 메모리를 차지한다. 따라서 필요치 않은 경우 밉맵을 꺼서 메모리를 아낄 수 있다. 또한 밉맵 텍스처들은 빌드에 포함되므로 비활성화시 파일 크기가 줄어드는 것도 확인할 수 있다.


7. Load From File

빌드 크기를 최소화하는 방법 중 jpg 혹은 png 같은 원본 이미지 파일을 실행 중에 동적으로 로드하는 방법이 있다. 압축 포맷이 지정된 텍스처라 하더라도 jpg 보다는 훨씬 큰 경우가 많다. 따라서 원본 이미지 파일을 bytes 형태로 Resources 하위 폴더에 넣어두고 실행 중에 Resources.Load 로 읽어서 텍스처로 만들게 되면 메모리는 증가하겠지만 빌드 크기를 줄일 수 있다.

Posted by 카코데몬
,
PlayMaker 패키지 임포트시 필요치 않은 파일들은 제외하는 것이 좋다. 다음 항목들은 필요시에만 포함시키자.
  1. iTween, Photon Unity Networking
  2. PlayMaker/Actions/Networking
  3. GetLocationInfo, StartLocationServicesUpdate, StopLocationServicesUpdate. ProjectLocation
    => GPS 퍼미션 요구
  4. Vibrate
    => Vibration 퍼미션 요구


'유니티 - PlayMaker' 카테고리의 다른 글

모든 PlayMakerFSM 컴포넌트로부터 Action 조회하기  (0) 2016.01.17
Animation Event 를 PlayMaker 로 전달하기  (0) 2016.01.12
PlayMaker 요약  (0) 2016.01.11
PlayMaker 소개  (0) 2016.01.10
Posted by 카코데몬
,