Unity/정보

[Unity] 모바일 게임 성능 최적화

달시_Dalsi 2024. 1. 2. 01:16

1편 https://www.youtube.com/watch?v=1mJtoceqvro 

 

2편 https://www.youtube.com/watch?v=RLcSRuZsZQU

 

유니티 공식 유튜브 채널에서 알려주는 팁이다. 알고 있으면 매우 도움이 되는 팁들을 알려주기에 한번 정독하면 좋을 듯 하다.


프로파일러

Window - Analysis - Profiler

 

병목현상이 나타나는 부분을 정확히 파악하기 위해 프로파일러를 사용해야한다.

프로젝트 마무리 단계에서만 하지말고 개발 초기부터 정기적으로 검사해주는게 좋다. 

 

프로파일링할땐 fps말고 ms를 확인하며 체크하는게 좋다.
fps와 ms는 1 fps = 10/ms,  1 ms = 10/fps 이런식의 관계가 적용된다. 그래서 프레임 한장을 그리기 위해 소모되는 시간을 각 항목별로 확인할 수 있으니 ms숫자가 높은 항목을 수정하는게 최적화에 도움된다. 
예로 1fps에 30ms가 걸리고 항목별로 보니 렌더링 5ms, 업데이트 5ms, 물리 20ms이면 물리부분을 보는게 좋다.

 

gpu쪽 병목인지 cpu쪽 병목인지 구분하여 확인하여 문제 해결을 해야한다.

실제론 cpu쪽 문제인데 gpu쪽 최적화를 더 해봤자 결과는 같기 때문이다.


디바이스 온도 - 폰은 온도가 높아질수록 성능이 낮아지는 상황인 쓰로틀링을 주의하며 테스트할 것 
쓰로틀링상태와 아닐때의 테스트 결과가 많이 다르기 때문이다.

 

유니티 프로파일러말고도 ios는 Xcode, 안드로이드는 Android Studio의 프로파일러를 이용하는 것도 좋다. 

Xcode, Android Studio 프로파일러는 유니티 프로파일러에서는 제공하지 않는 항목들도 확인 할 수 있다.


메모리

메모리 프로파일링도 있다. 이는 패키지 매니저에서 설치를 따로 해줘야 한다.

PC에서는 메모리가 조금 부족해도 저장장치에서 조금씩 빌려와서 사용하기에 갑자기 꺼지거나 하는 상황이 적다. 하지만 모바일에선 그런 기능이 기본적으로 없기 때문에 PC보다 갑자기 꺼지는 상황이 많이 발생한다. 그러므로 메모리관리를 잘해야한다. 


메모리 부족하다고 텍스쳐만 보지말고 프로파일러를 사용하여 주요 항목을 체크하여 해결하자.

https://www.youtube.com/watch?v=rdspAfOFRJI

 


c#의 장점이자 단점 - GC(가비지 콜렉터) 
메모리 할당이 많아질수록 GC부담이 많아지니 메모리 할당을 최대한 줄이자
문자열 주의 - json, xml은 전부 문자니 , 애니메이션 변환시 문자열 주의 m_Animator.SetBool("Jump", ture); 이런거 string인자 사용하면
이 기능을 사용할때마자 GC에 부담주니 string말고 id로 받아와서 사용하는걸 추천. Animator.StringToHash를 통해 아이디 얻어서 사용
GameObject.CompareTag를 사용하는게 좋다
코루틴도 new 최대한 적게 사용하기 위해 최초 new를 캐싱해서 사용하기 
boxing : 참조 유형 변수 대신 값 유형 변수를 전달하지 마십시오. 이는 임시 객체를 생성하고 그에 따른 잠재적 쓰레기는 암시적으로 값 유형을 유형 객체로 변환합니다.
박싱도 주의

빈 함수 제거 ex) update, start

최종 빌드일땐 디버그 로그 제거하거나 #if UNITY_EDITOR #endif 사용하여 에디터에서만 사용하게끔 하던가 

add컴포넌트 기능은 쓰지마라 차라리 같은 프리팹을 여러개 생성해놓고 다른 컴포넌트를 각각 붙여주는게 좋다
컴포넌트 사용할땐 캐싱을 해서 사용해라 ex)Renderer myRenderer = GetComponent<Renderer>();

오브젝트 풀 사용 이때 주의점, 리페어런팅(setparent)은 왠만하면 하지마라 하이라이키에서 볼때 정리된다고 사용 금지 
스크립터블 오브젝트 적극 사용하기 

오브젝트 세팅, 플레이어 세팅에서 여러 옵션이 되게 많은데 필요없는 옵션은 전부 끄거나 줄여라

쓰로틀링 방지 및 발열 방지를 위해 필요이상으로 fps나오는걸 방지하기 위해 fps제한 걸기
예로 액션게임같은경우는 fps가 높아야하지만 퍼즐게임 같은 경우는 fps가 그렇게 중요하지 않으므로 낮게 제한해서 발열을 잡을 수 있다.
그러니 본인의 게임 목표 fps를 책정하는게 좋다 

간단한 하이어라이키 - 자식 오브젝트가 많을수록 부모 오브젝트가 움직일때 전부 계산해야하므로 하이어라이키는 될수있으면 간단하게 


텍스쳐

아틀라스

텍스쳐도 아틀라스 사용할 수 있으면 사용하자 

텍스쳐별로 POT사이즈가 아닐경우가 있는데 이때 아틀라스를 사용하면 한개로 묶이면서 크게 POT사이즈로 변경된다.

 

모바일에선 텍스쳐 사이즈를 최대 2048로 하자 

 

read/write endabled는 체크 해제한다. 예외적으로 런타임 중에 텍스쳐가 변경되거나 하는 일이 있다면 키자.

Generate Mip Maps - 3d에서 사용하고, 2d는 사용할 필요 없으니 끈다. 

텍스쳐 압축은 무조건 사용한다.


메쉬

메쉬 파일 - 안쓰는 옵션은 끄자
read/write endabled - 동적으로 매쉬조작하는게 아니라면 끄자
메쉬 압축(Mesh Compression) - 사용하면 좋은데 데이터 정밀도가 떨어져서 품질저하가 우려되니 확인하면서 작업하기
Rig와 Blend Shape Normals 사용하지 않으면 끄자
노말맵을 사용하지 않으면 Tangents를 끄자 


그래픽

URP 사용이 대체로 좋다.

URP 사용 이전 프로젝트에 URP 추가하는건 잘 고려하고 교체해야 한다. 이전의 작업들이 자동으로 적용이 안되는 경우가 있기 때문이다. 

새로 프로젝트 생성하는 경우에는 URP를 사용하자 

드로우콜(draw call)/배치(batches)를 신경쓰자

아래 영상에서 잘 정리되어 있으니 한 번 보자

https://www.youtube.com/watch?v=w14yjBlfNeQ

 

 

중요하지 않은 오브젝트들은 매쉬렌더러의 그림자 비활성화하고 실제 그림자처럼 꾸미거나 하는 방식이 더 저렴하게 먹힌다.

 

정적인 물체에는 라이트맵을, 동적인 물체에는 라이트 프로브를 사용하자 

이 블로그에서 자세히 정리해놓았으니 살펴보자.

https://adri.tistory.com/30

 

[Unity] Lightmapping Settings

References Unity에서의 조명 환경 Baked Lighting 이해하기 Unite Now: URP와 GPU Lightmapper 내 조명 표현 Unite Europe 2017: Bake it 'till you make it: An Intro to Lightmap Lighting Windows 라이팅 창 - Unity 매뉴얼 라이팅 창(메뉴

adri.tistory.com

 

멀어짐에 따라 품질이 낮아지는 LOD사용

https://docs.unity3d.com/kr/2021.3/Manual/class-LODGroup.html

 

LOD 그룹 - Unity 매뉴얼

LOD Group 컴포넌트는 게임 오브젝트의 디테일 수준(LOD)을 관리합니다.

docs.unity3d.com


오쿨루젼 컬링 (Occlusion Culling) 본인의 프로젝트 상황에 따라 사용했을때 이득이면 사용할 것

특히 야외에서는 사용하지 않는게 좋고 실내 공간에서 자주 쓰인다고 한다.

 

핸드폰마다 해상도가 너무 다르다. 그리고 최신폰의 경우 해상도가 너무 높기 때문에 네이티브 해상도 그대로 사용하면 안된다. 이를 해결하기 위해 UI는 원래 해상도 사용하고 3D화면은 해상도를 낮추는 방법을 사용한다. 이를 URP에선 Render Scale 옵션을 조절하면 된다.

카메라 갯수는 줄일 수록 좋다. (시네머신은 실제 카메라가 아니므로 상관 없다)

코딩할때 Renderer.material를 호출하면 임시로 머티리얼 복사본이 만들어지기 때문에 비효율적이게 된다. 
여러 오브젝트에 동일하게 적용된 머티리얼에 접근할땐 Rendrer.sharedMaterial 사용하도록 하자

리플렉션 프로브는 연산이 많이 들어가니 사용 최소화하기


UI

캔버스를 동적, 정적으로 분활하자. 

드로우 콜이 캔버스 단위로 발생하기 때문에 하나의 캔버스 안의 요소가 하나 업데이트되면 동일 캔버스안의 다른애들도 업데이트되기 때문이다. 그렇기 때문에 캔버스를 하나만 사용하지말고 자주 업데이트되는 캔버스, 아닌 캔버스로 나눠서 작업하자.

 

 

캔버스 밖에 있는 흰색 이미지는 비활성화하자

보이지않은 UI는 비활성화하자. UI가 카메라 범위안에 없어서 안보여도 연산은 들어가기때문에 안보이면 비활성화해야한다.

 

 

UI중에 상호작용이 없는 오브젝트는 Raycast Target 기능 비활성화하기

Raycast Target은 버튼같이 상호작용이 되는 요소에만 활성화하고 배경화면 같은 경우는 끄면 된다. 

 

 

Graphic Raycaster 컴포넌트가 버튼 클릭을 담당해주는 컴포넌트인데 이는 보통 캔버스에 달려있다.

이 컴포넌트의 하위오브젝트들이 전부 영향 받기에 버튼만 있는 옵젝에 넣어주면 좋다.

다만 UI 작동이 되게 단순하기 때문에 반드시 그럴 필요는 없다.

 

 

그리드 레이아웃 그룹(Grid Layout Group) - 동적 연산하는애라 안쓰는게 좋은데 꼭 써야한다면 ON/OFF 기능을 만들어서 

정렬할때만 켰다가 끄는 방식을 생각해보자.

 


유니티에서 디바이스 시뮬레이터를 제공하기에 이를 활용하자.

Preject Settings에서 Package Manager의 Preview Packages를 활성화한뒤 검색하여 설치하자.

 

 

기종별로 노치같은것도 확인할 수 있다.


오디오

사운드 클립 중 단일채널로 사용해도 된다면 ForceToMono 옵션등을 체크하여 mono로 설정하는게 좋다. 

대체로 캐쥬얼 모바일게임에선 단일채널 사운드만 있으니 자신의 프로젝트에 쓰이는 사운드를 잘 확인해보자.

 

mp3보단 wav를 사용하자

어떤 파일형식이든 유니티에서 사용할때 자동으로 다시 압축하고 사용한다. 그래서 이미 다른 확장자로 변경하는 과정에서 손실이 일어난 파일들보단 원본인 wav확장자를 사용하는게 손실없이 좋다. 

 

 

사운드 압축은 반드시 해야한다.

압축 옵션 중에 Compression Format은 왠만하면 Vorbis로 한다. 다만 짧은 사운드는 ADPCM사용한다.
Load Type은 decompress on load - 되게 짧은 사운드 / compressed in memory - 중간크기 사운드 / streaming - 큰 용량 사운드(배경음악 등)로 각각 사운드 파일에 맞는 설정해주자.

 

 

오디오 소스로 사운드를 출력할때 볼륨이 0이라도 연산이 들어가기에 그냥 mute를 활성화하여 아예 끄는게 좋다. 


애니메이션

Rig의 Animation Type 중에 humanoid는 generic보다 30~50% 메모리를 더 쓴다.

humanoid에서만 사용할 수 있는 기능이 여럿 있으니 당연히 연산이 더 들어간다. 그러므로 두가지다 사용가능하면 generic을 사용하자. 


물리

Playersettings에 Optimization-Prebake Collision Meshes는 체크하는게 좋다 

충돌처리할 곳을 미리 굽는다고 한다.

 


Layer Collision Matrix - 레이어별로 충돌 간섭을 할건지 안할껀지 체크하는건데 필요없는건 체크해제하여 연산하지 않도록 하자. 


콜라이젼

콜라이더는 당연히 매쉬보다 간단한 기본 도형 콜라이더가 좋다. 왠만하면 기본 도형 콜라이더를 사용하자.

 

 

 

 

 

 

 

'Unity > 정보' 카테고리의 다른 글

[Unity] New Input System  (1) 2024.01.13
[Unity] 오브젝트 풀링 (Object pooling)  (0) 2024.01.06
[Unity] 사운드 매니저  (0) 2023.12.03
[Unity] AOS Fog of War 에셋  (0) 2023.12.02
[Unity] DOTween 사용하기  (0) 2023.11.27