스프라이트 아틀라스 프로퍼티 생성 방법
Sprite Atlas 를 생성하려면 메뉴에서 Asset > Create > Sprite Atlas 로 이동하십시오. 그러면 Unity가 에셋 폴더에 *.spriteatlas 파일 확장자가 붙은 스프라이트 아틀라스를 생성합니다.
* 나도 여기다 정리하고 내가 볼라고 쓰는글 ...
Tight Packing : 지정한 Max Texture Size (1024)안에서 남는 여백에 rotate하면서 꽉꽉 채워서 이미지가 합쳐진다.
(using alpha area tightly)
@@ Unity Atlas overlay 이미지 겹치는 문제 :
갑자기 이미지가 여러개 섞여서 나왔다. => Max Texture Size 가 넘친거다.. => 1024 -> 2048 로 간단히 해결
어떻게 알수 있나는 잘 모르겠고, 큰 사이즈 부터 Packing 하면서 Preview보면서 여백 남는거 보면서 Texture Size를 조절하면 될 것 같다.
@@ Atlas 이미지 저하 :
근데 이미지 quality 가 계속 Filter Mode와 다르게 나왔다.
보니까 기본 이미지 자체에서 Filter설정을 하고,
아틀라스 압축은 또 따로였다.
기본이미지를 nofilter, none으로 했다...
(어디선가 읽어봤을때 trilinear도 괜찮다고 들었던것 같은데 nofilter가 어디서 꺠질 수 있따고 ...? 이부분은 찾으면 수정해야지)
듣로우콜 : 한번에 그리는/로드하는 GPU 량인데 Batch로 확인해 볼 수 있다 ..
텍스처 최적화
#unity 이미지 2의 제곱
Unity를 사용하면서 이미지를 2의 제곱으로 사용해야된다고, 안그러면 메모리 낭비가 된다는 말을 계속 들어왔다.
관련해서 좋은글을 찾았다! POT
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 로 읽어서 텍스처로 만들게 되면 메모리는 증가하겠지만 빌드 크기를 줄일 수 있다.
출처: https://cacodemon.tistory.com/entry/텍스처-최적화 [카코데몬의 잡동사니]
UI 최적화 테크닉
이미지 최적화를 위해서 여러글을 찾아보다가..
이글이 제일 잘 정리된 것 같다. 이글 최고당.... 다 주옥같은 글이어서 다 퍼왔음.
- 배치(Batch)에 대해서 알아야 할 부분이 있는데, 배치는 해당하는 이미지를 출력 하기 까지 필요한 연산으로 보시면 됩니다.
-
아주 작은 이미지의 경우 공용 Atlas에 넣어넣고 끌어다가 쓰는 경우도 있는데, 경우에 따라서는 메모리 낭비가 됩니다. 작은 이미지 하나 때문에 다른 Atlas 를 불러오는 것 보다 해당하는 작은 이미지를 현재 페이지가 사용하는 Atlas에 넣고 쓰는 편이 좋습니다. 공용 Atlas는 제작 방법에 따라 다르지만, 보통 32bit무압축에 2048 사이즈를 자랑하기에 16메가나 되는 이미지 메모리를 무조건 쓰게 됩는 결과를 만듭니다. 그리고 이 이미지 때문에 드로우콜이 증가하게 됩니다.
Atlas - 모든 UI를 합쳐서 한장의 Atlas로 묶을 수 있으면 한장으로 묶어서 사용. 언제나 텍스쳐 한장은 메모리에 상주 시키는 방법이 좋습니다. 디자인 - UI의 디자인이 너무 다채롭고 어렵다면, 완성된 UI 이미지를 씬 별로 나누어서 제작 하는 편이 유리할 때도 있습니다. TA와 상의하세요~ Batch - 그래디언트가 많고 넓은 면적을 차지하는데 여러 Atlas를 거쳐서 사용해야 하는 디자인은 60 Batch이하라면 사용할 만 합니다. 드로우콜이 60을 넘어가면 저사양 모바일에서 프레임 드랍과 발열 문제가 발생합니다. |
filter Mode
-Point
-Trilinear
-Bilinear
Filter Mode:
Select how Unity filters packed Textures when they stretch during transformations. This setting overrides the Filter Mode setting of any packed Sprite in the Atlas. For more information, see the Filter Mode Texture import option.
4. Batch와 SetPass Call, FPS
Batch = Draw Call + Set VB/IB(mesh) + Set Transform + Set Shader + Set Texture 0~9.... + Set Blending + Set Z enable + Set Z Test + Set . . . 많습니다.
같은 ATlas라고 하더라도 매터리얼(shader)이 다르면 SetPass Call이 증가 합니다.
Batch가 같은 양이라고 하더라도 SetPass Call이 많다면 느려집니다.
이는 Unlit 셰이더와 PBR셰이더의 연산 속도가 다른것과 비슷합니다.
다음 자료는 기기별 FPS수치 입니다. 다른 코드가 없는 순수 FPS 기준의 수치 입니다.
Device |
Obj(384 tris) - 1 SetPass Call |
Batches(60fps limit) |
Samsung Galazy S2 |
32,640 |
85 |
Samsung Galazy S3 |
68,352 |
178 |
Samsung Galazy S4 |
82,560 |
215 |
Samsung Galazy S5 |
99,840 |
260 |
1 Passcall 을 사용할 때 최대 배치 수 입니다. 화면을 차지하는 작은 이미지 기준이며, 해당 배치는 화면을 차지하는 영역이 넓은 Alpha blending 오브젝트라면 더 낮게 계산 될 수도 있습니다.
지금 까지의 모바일 기기의 UI에서는 60 배치 이하로 사용하시는 편이 좋습니다.
5. Draw Call 과 Canvas
UGUI는 Canvas마다 각자의 Vertex buffer를 가지고 있기 때문에 Canvas가 두개면 최소 두번의 Draw Call이 일어납니다. 이는 Canvas 하위에 canvas가 존재하는 경우에도 증가하게 됩니다.
한번에 그려야 할 경우 하나의 캔버스 안에 넣어 주면 드로우콜을 줄일 수 있습니다.
Text(글씨 폰트) 는 별도의 TExture를 사용하기 때문에 별도의 Draw call로 발생 합니다.
폰트 별로 만들어 지기 때문에,폰트의 종류를 줄이면 드로우콜이 줄어듭니다.
Culling
가장 빠르게 그리는 방법은 아무것도 그리지 않는 것 입니다. 화면에 가려져 있거나 안보이는 부분은 아예 그리지 않도록 제작 합니다.
Canvas를 여러개 써야 한다면 각각의 역할에 나누어서 캔버스를 할당 합니다. 배경 담당, 폰트 담당, 동적 오브젝트 이펙트 담당 등 영역과 역할을 나누고, Atlas를 따로 관리 하는 것도 좋은 방법 입니다.
Batch를 증가 시키는 방법 |
렌더 속도를 느리게 하는 방법 |
- Atlas가 아닌 개별 이미지의 개수를 늘립니다. - 다른 Atlas 의 이미지와 겹치게 배치 합니다 - 같은 Atlas로 된 이미지들 사이에 Dynamic Particle 을 배치 합니다. - 하나의 Atlas지만 Material을 다른 것으로 적용 합니다. - 여러 개의 Mask 내에 Atlas를 배치 합니다. - UI에 파티클 이펙트를 여러 개 사용 합니다. - .... |
- Tween 보다 Animation을 사용 합니다. - Animator 컴포넌트를 여러 개로 분리해서 사용 합니다. - 같은 Atlas여도 넓은 면적을 여러 번 겹쳐서 출력 합니다 - 그라디언트(Alpha) 오브젝트를 넓은 면적에 여러 번 출력 합니다 - 폰트나 이미지에 특수 효과를 많이 적용 합니다. - 팝업 창을 여러 개 띄우기 - ... |
위에 예시처럼 만들면 망하겠죠? 후후후.
6. UI 최적화 방법
다음 링크는 Unite Europe 2017 최적화 영상 자료 입니다.
정리된 자료를 퍼 왔습니다.
Unite Europe 2017 - Squeezing Unity: Tips for raising performance
Mark and Ian from Unity's Enterprise Support team run through performance best practices drawn from real-world problems. Learn the underlying architecture of...
youtu.be
•캔버스 분할
문제: UI 캔버스에서 한두 가지 요소를 변경하면 캔버스 전체가 변경된 것으로 인식됩니다.
캔버스는 유니티 UI의 기본 컴포넌트입니다. 캔버스에 배치된 UI 컴포넌트를 나타내는 메시를 생성하고, UI 컴포넌트가 변경되면 메시를 다시 생성하며, GPU에 드로우 콜을 발행하여 UI가 실제로 표시되도록 합니다.
이러한 메시를 생성하는 데는 많은 자원이 소모될 수 있습니다. UI 요소를 배치로 수집하여 드로우 콜 횟수를 가능한 한 줄여야 합니다. 배치 생성에는 많은 자원이 소모되므로 필요한 경우에만 재생성하는 것이 좋습니다. 여기서 문제는 캔버스에서 하나 이상의 요소가 변경되면 전체 캔버스를 다시 분석하여 요소를 드로우하는 최적의 방식을 파악해야 한다는 점입니다.
솔루션: 캔버스를 분할합니다.
각 캔버스는 포함된 요소를 다른 캔버스의 요소로부터 분리하는 섬과 같습니다. 따라서, 기본 툴에서 캔버스를 분할하면 유니티 UI의 배칭 문제를 해결할 수 있습니다.
캔버스를 중첩할 수도 있습니다. 그러면 디자이너가 여러 캔버스에 걸쳐 다양한 요소가 화면의 어느 위치에 표시되는지 고민할 필요 없이 대규모의 계층적 UI를 생성할 수 있습니다. 자식 캔버스도 부모 캔버스와 형제 캔버스 모두로부터 콘텐츠를 분리할 수 있으며, 자체적으로 지오메트리를 유지하고 자체 배칭을 수행합니다.
캔버스를 자식 캔버스로 더 세분화하는 경우, 동적 요소를 정적 요소와 분리하는 등 업데이트 시점에 따라 요소를 그룹화하는 것이 좋습니다. 비디오의 29분 36초 부분에 스마트한 캔버스 세분화의 좋은 예를 설명합니다.
•최적의 그래픽 레이캐스터(Graphic Raycaster) 사용
문제: 최적의 그래픽 레이캐스터 사용법
그래픽 레이캐스터(Graphic Raycaster)는 입력 사항을 UI 이벤트로 변환하는 컴포넌트로, 화면/터치 입력을 이벤트로 변환한 다음 관련 UI 요소로 전송합니다. 하위 캔버스를 비롯하여 입력이 필요한 모든 캔버스에 그래픽 레이캐스터가 있어야 합니다.
이름과는 달리 그래픽 레이캐스터는 실제로 레이캐스터가 아니며, 기본적으로 UI 그래픽만 테스트합니다. 그래픽 레이캐스터는 특정 캔버스에 입력을 수신하는 UI 요소를 포착하고 교차 지점을 확인합니다. 즉, 그래픽 레이캐스터 캔버스에 포함된 각 UI 요소의 RectTransform에 대해 입력 이벤트가 발생하는 지점이 인터랙티브로 표시되는지 확인합니다.
여기서 일부 UI 요소의 경우 업데이트 수신과 관련이 없다는 점이 문제가 됩니다.
솔루션: 정적 요소나 비인터랙티브 요소에 대한 레이캐스트 타겟을 비활성화합니다.
텍스트 또는 버튼이 이러한 요소에 해당합니다. 레이캐스트 타겟을 비활성화하면 그래픽 레이캐스터가 각 프레임에 대해 수행해야 하는 교차 지점 검사 횟수가 즉시 감소합니다.
문제: 그래픽 레이캐스터가 어떤 측면에서는 레이캐스터의 역할을 합니다.
캔버스에서 렌더 모드를 월드 공간 카메라나 화면 공간 카메라로 설정하는 경우 차단 마스크를 설정할 수도 있습니다. 차단 마스크는 레이캐스터가 2D 또는 3D 물리를 통해 레이캐스트를 수행할지 결정하여 일부 물리 오브젝트가 사용자와 UI 간의 상호작용을 차단하는지 확인합니다.
솔루션: 2D 또는 3D 물리를 통한 레이캐스트는 많은 자원을 소모하므로 최대한 적게 사용합니다.
또한, 인터랙티브 이벤트를 확인할 필요가 없는 비인터랙티브 UI 캔버스에는 그래픽 레이캐스터를 추가하지 않음으로써 그래픽 레이캐스터의 수를 최소화하세요.
•Camera.main 사용 지양
문제: 상호작용 이벤트를 전송한 카메라 정보가 월드 공간(World Space) 캔버스에 제공되어야 함.
월드 공간 또는 카메라의 스크린 공간에서 렌더링하도록 캔버스를 설정하는 경우, UI의 그래픽 레이캐스터를 위한 상호작용 이벤트를 생성하는 데 사용할 카메라를 지정할 수 있습니다. 이 설정은 “스크린 공간 - 카메라” 캔버스에 필요하며, "렌더 카메라"라고 불립니다.
그러나 “월드 공간” 캔버스의 경우 이 설정은 선택 사항이며, "이벤트 카메라(Event Camera)"라고 불립니다.
월드 공간 캔버스의 이벤트 카메라 필드를 비워 두는 경우에도 캔버스는 게임의 기본 카메라를 사용하여 이벤트를 수신하며, 어느 카메라가 기본 카메라인지 파악하기 위해 카메라 기본 속성에 액세스합니다.
유니티가 사용하는 코드 경로에 따라 캔버스는 프레임당, 그래픽 레이캐스터당, 월드 공간 캔버스당 Camera.main에 7~10회 접속합니다. Camera.main은 액세스될 때마다 Object.FindObjectWithTag를 호출하므로 이로 인해 런타임이 지연될 수 있습니다.
솔루션: Camera.main 사용을 지양합니다.
카메라 레퍼런스를 캐싱하고 기본 카메라를 추적하는 시스템을 구축하세요. 월드 공간 캔버스를 사용하는 경우 항상 이벤트 카메라를 할당하세요. 이 설정을 절대 비워두지 마세요. 이벤트 카메라를 변경해야 하는 경우 이벤트 카메라 프로퍼티를 업데이트하는 코드를 작성하세요.
•가능한 한 레이아웃 그룹 지양
문제: GetComponents 호출을 최소 1회 수행하여 레이아웃을 변경하려고 하는 모든 UI 요소
레이아웃 시스템에서 하나 이상의 자식 요소가 변경되면 레이아웃 시스템이 변경된 것으로 인식됩니다. 변경된 자식 요소는 해당 자식 요소를 가지는 레이아웃 시스템을 무효화시킵니다.
레이아웃 시스템 간략 정보: 레이아웃 시스템은 레이아웃 요소 바로 위에 있는 인접한 레이아웃 그룹입니다. 레이아웃 요소 컴포넌트뿐만 아니라 UI 이미지, 텍스트, 사각 스크롤 영역 역시 레이아웃 요소에 해당됩니다. 또한, 사각 스크롤 영역은 레이아웃 그룹에도 해당됩니다.
문제로 다시 돌아가서, 레이아웃을 변경하려고 하는 각 UI 요소는 최소 1회의 GetComponents 호출을 수행합니다. 이 호출은 레이아웃 요소의 부모 수준에서 유효한 레이아웃 그룹을 찾습니다. 유효한 레이아웃 그룹을 찾으면 더 이상 레이아웃 그룹을 찾을 수 없거나 계층 구조의 루트에 도달할 때까지(어느 쪽이든 먼저 발생할 때까지) 변환 계층 구조 상위로 계속 진행합니다. 따라서 각 레이아웃 그룹은 각 자식 레이아웃 요소의 변경 프로세스에 1회의 GetComponents 호출을 더함으로써 중첩된 레이아웃 그룹의 성능을 극도로 저하시킵니다.
솔루션: 가능한 한 레이아웃 그룹을 지양합니다.
비례 레이아웃의 경우 앵커를 사용하세요. 요소 개수가 변화하는 핫 UI의 경우 레이아웃을 계산하는 자체 코드를 작성하되 변경 사항이 발생할 때마다 사용하지 말고 필요한 경우에만 사용하도록 하세요.
•스마트한 방식으로 UI 오브젝트 풀링
문제: UI 오브젝트를 잘못된 방식으로 풀링합니다.
대부분의 경우 UI 오브젝트의 부모 수준을 변경한 다음 비활성화하여 풀링하지만 이러한 방식은 불필요한 변경을 초래합니다.
솔루션: 먼저 오브젝트를 비활성화한 다음, 부모 수준을 풀로 변경합니다.
그러면 기존의 계층 구조를 1회 변경하게 되지만, 부모 수준을 바꿀 때에는 기존 계층 구조를 다시 변경하지 않으며, 새로운 계층 구조는 전혀 변경하지 않게 됩니다. 풀에서 오브젝트를 제거할 때에는 먼저 부모 수준을 바꾼 다음 데이터를 업데이트하고 활성화하세요.
•캔버스를 숨기는 방법
문제: 캔버스를 숨기는 방법
일부 UI 요소와 캔버스를 최대한 효율적으로 숨기는 방법은 무엇일까요?
솔루션: 캔버스 컴포넌트 자체를 비활성화합니다.
캔버스 컴포넌트를 비활성화하면 캔버스가 더 이상 GPU에 드로우 콜을 발행하지 않으므로 캔버스가 보이지 않게 됩니다. 하지만 캔버스는 버텍스 버퍼를 폐기하지 않으며 모든 메시와 버텍스를 유지하므로, 캔버스를 다시 활성화하면 리빌드를 트리거하지 않고 다시 드로우하게 됩니다.
또한 캔버스 컴포넌트를 비활성화하더라도 캔버스의 계층 구조에서 많은 자원을 소모하는 OnDisable/OnEnable 콜백이 트리거되지 않습니다. 단, 많은 자원을 소모하는 프레임당 코드를 실행하는 하위 컴포넌트를 반드시 비활성화하세요.
•UI 요소에 애니메이터를 사용하는 최적의 방식
문제: UI에서 애니메이터 사용
애니메이터는 애니메이션의 값이 변경되지 않더라도 모든 프레임의 요소를 변경하며, 무연산 검사 기능이 없습니다.
솔루션
항상 변화하는 동적 요소에만 애니메이터를 적용하세요. 변화 빈도가 낮거나 이벤트에 대한 반응으로만 단기간 동안 변화하는 요소의 경우 자체 코드를 작성하거나 트위닝 시스템을 구축하세요(에셋 스토어 확인).number on the Asset Store).
'DEV > Unity' 카테고리의 다른 글
[sloved] Unity click button through image (click over the other images) (0) | 2020.12.30 |
---|---|
[solved] unity UI Text Color change separately 부분 색 바꾸기 (0) | 2020.12.26 |
[solved] Unity Scroll View position initialize (1) | 2020.12.19 |
Unity ads error Banner fail (0) | 2020.12.19 |
[solved] UnityWebRequest Get noneArray Type error (0) | 2020.12.19 |