[유니티 TIPS] 모바일 게임 성능 최적화 - 1편
 
Profiling 
- 최적화할때 프로파일링은 필수 
- 최적화는 수시로 해야 한다. 
- 프로토타입은 할 필요 없다. 어차피 바뀌는게 많으므로 
 
- 맹목적으로 하지 말것 
- 에디터가 아닌 모바일 타겟 디바이스에서 돌려봐야 한다. 
- Xcode intstruments를 이용하면 유니티 프로파일링보다 더 디테일하게 볼 수 있다.  
- 안드로이드는 스냅드래곤이나 Android Studio등 다양하게 있으니 확인해보자. 
- Profiler Analyzer를 이용하면 프로파일링을 스냅샷하여 before after같은 성능 변화 추이를 볼 수 있다. 
- 성능측정을 할땐 FPS에보다는 ms(milliseconds)를 이용하자 
- ms는 1프레임을 그릴때 걸리는 시간을 1/1000초로 환산한것이다 
- FPS = 1000/ms 
- Ms = 1000/FPS 
 
- 예를들어 특정 프레임이 총 30ms가 걸리는데… 
- Rendering 5ms 
- Update 5ms 
- Phygics 20ms 
- 라고 한다면 Phygic를 최적화하는것이 제일 효율적일 것이다. 
  
 
 
- 병목이 GPU bound인지, CPU bound인지 확인하자 
- 모바일 디바이스는 발열에 주의하자 
- 측정할때 쓰로틀링에 빠지면 신뢰할 수 없는 결과가 나온다 
 
- 스마트폰과 태블릿은 해상도가 다르기 때문에 병목에 GPU bound가 생길수도 있으니 확인하자. 
Memory 
- Memory Profiler를 이용하자 
  
- Texture보다는 RenderTexture와 Shader가 더 메모리를 사용하므로 최적화하는 Texture를 수정하는건 의미없다 
 
- PC 
- Storage를 메모리가 빌려쓸 수 있다. 그래서 게임이 16GB를 사용하는데 RAM이 8GB더라도 뻗지 않는다 
 
- Mobile 
- Storeage를 메모리로 쓸 수 없다. 그래서 모바일에서는 해당 RAM을 사용하면 OS에서 앱을 강제종료 시켜버린다 
 
- GC는 항상 염두에 두자 
- GC가 자주 도는것은 spike의 원인 
- String 
- JSON이나 XML을 사용할때 string을 파싱하는데 그 string이 GC의 대상이 된다 
- 배포단계에서는 JSON이나 XML을 ScriptableObject로 변환하여 사용하는것이 좋다(자동화 추천) 
 
- Animator 
- Animator.SetBool 같은 함수에 파라미터로 string을 넘기는 것은 string이 GC의 대상이 된다. 대신 Id값을 넘기도록 하자. 
- Id를 얻어오는 것은 Animator.StringToHash를 사용 
 
- Unity Function calls 
- Tag를 비교할 땐 GameObject.tag == 보다는 GameObject.CompareTag를 사용하는것이 좋다. Tag는 garbage를 발생시킨다 
 
- Coroutine 
- yield return new WaitForSeconds 보다는 yield return cachaedWaitForSeconds 처럼 캐시하여 사용하자 
 
 
- Adaptive Performance(삼성 디바이스) 
- 현재 쓰로틀링 직전인지, GPU바운드인지 등등의 상태를 알 수 있어서 런타임 최적화를 할 수 있으니 적극 활용하자 
 
- 빈 함수는 제거하자 
- Start, Update문같은것도 빈 함수로 두면 영향을 끼친다 
- Define symbol을 활용하자 
- System.Diagnostics.Conditional 을 활용하자 
 
- Componet사용 주의 
- AddComponent는 사용을 지양하자. 
- GetComponet는 캐시해서 사용하자 
 
- 오브젝트 풀 사용 
- 주의할점은 오브젝트 풀을 사용하면서 Active/Deactive식으로 나눈 후 부모를 바꾸지 말것. 
- SetParent가 생각보다 성능을 잡아먹는다. 
 
- ScriptableObject 사용하기 
- MonoBehaviour를 상속받아서 프리팹으로 사용하게 되면 Serialized를 하게 된다 
- ScriptableObject는 이미 Serialized가 되었기 때문에 성능적인 면, 관리적인 면에서 이득이다. 
 
- Project Configuration 
- 프로젝트 설정에는 선택해야하는 항목들이 많다 
- 키워드는 "끄거나 줄여라" 
- 프로젝트에 필요없는 것들은 끄거나 줄여야한다 
- 끄자 - 중력센서,  등등 
- 줄이자 - Auto Graphics API대신 원하는 플랫폼에 맞춰 추가 
 
- 불필요한 physics 연산(auto simulation, auto sync transforms)은 사용하지 않는다 
- Physics는 물리공간이 별도로 존재한다. 
- Scene뷰의 객체들과 물리공간의 객체들은 데이터가 동기화되어야 하는데, auto sync transforms를 사용하면 자동으로 동기화를 시켜준다 
  
- 
연산이 필요한 부분이기 때문에 물리가 중요하지 않는 게임들은 꺼주는게 좋다 
 
 
- Application.targetFrameRate를 프로젝트별로 알맞게 설정한다(RPG=60, PUZZLE=30 ….) 
- 큰 하이라키 구조는 피한다 
- A부모에 A', A'', A''' 등등의 자식들이 많아질수록 A부모 transform이 움직였을때 자식들의 transform도 재계산이 이루어진다 
- A부모와 B부모, C부모.. 등등 부모가 잘 쪼개어지면 각 부모를 멀티스레드 연산으로 병렬적으로 돌릴 수 있기 때문에 하이라키 구조를 잘 구성하자 
- transform의 position, rotation등등 값들은 한번에 처리하는 것이 좋다 
- 각 속성에 값을 set할때마다 transform연산이 일어난다 
- 위의 큰 하이라키 구조라면 자식들의 모든 transform연산도 일어난다 
- Transform.SetPositionAndRotation을 이용한다 
- Instantiate(prafab, parent) 대신 Instantiate(prefab, parent, position, rotation) 을 사용하자 
 
 
- Vsync는 꺼주자