(유니티3D)최적화 공부와 프로파일러
팀프로젝트로 모바일 게임을 만들면서 제일 많이 느낀게 바로 최적화였습니다.
지스타 시연용으로 사용하는 기기가 갤럭시 노트 10(이후 갤노트)이었던 것도 한몫 했지만 발열과 배터리 소모량도 무시할 수 없었기 때문이죠.
퀄리티 부분에서 많은 희생이 따른 결과 갤노트에서도 아주 원활하다고는 할 수 없지만 플레이에 큰 지장을 주지 않을 정도로 프레임을 뽑아냈고 또 다른 시연 기기인 노트4는 8시간 풀로 켜놔도 미지근한 정도의 발열을 보여주었습니다.
하지만 지스타 부스들 중 대기업에서 낸 모바일 게임들을 보면 과장 조금 보태서 그래픽이 거의 PC를 그대로 가져온듯하면서 프레임 또한 잘 나오는 것을 보면 정말 놀라지 않을 수 없습니다.
물론 그 게임은 프로들이 다수 모여서 만들었으니 그럴 수 있겠지만 제 목표 또한 그런 사람들이기 때문에 많은 자극을 받았고 이후 메모리 관리 관련 글들을 수시로 찾아 보고 있습니다.
최적화에는 여러 방법이 있습니다.
사용하는 프로그래밍 언어 자체에서 관리할 수도 있고 요즘의 경우 엔진에서 관리해 줄 수도 있습니다.
둘 다 중요하지만 지금은 유니티엔진에 우선순위를 두어 공부를 하고 있습니다.
유니티는 C# 스크립트를 사용하기에 C#도 같이 공부하게 되는 효과가 있고요.
구글에 유니티 최적화를 검색하면 정말 많은 글들이 나옵니다.
모두 적용 할 수 있으면 정말 좋겠지만 당장은 어디가 어떤 문제를 가지고 있는지 정도만을 파악하고 약간의 수고만으로 적용이 가능한 최적화 기법들에 익숙해지기로 했습니다.
기본적으로 큰 영향을 끼치는 부분들은 대부분 알고 계시리라 생각합니다.
오브젝트의 생성과 파괴를 오브젝트 풀로
GetComponent나 Find 같은 함수들은 써야한다면 Awake와 같은 초기화 함수에서 실행하고 그 얻은 주소를 지니고 있을 것
ToString의 남용 금지
이러한 부분들은 이미 숙지하고 사용하고 있었습니다만 모바일 환경에선 티끌이 모이면 정말 크게 다가옵니다.
그래서 앞으로는 더 신경써서 위 방법 이외의 방법을 사용해 코드를 작성하려 하고 있습니다.
일단 다른 분들의 블로그를 보고 당장 실천하고 있는 부분은
자주 쓰는 클래스의 구조체화
StringBuilder를 사용
코루틴에서 반복 사용되는 new WaitFor~ 의 경우 따로 선언 해두고 그것을 사용 등
가비지 생성을 최소화 하려고 노력중입니다.
그리고 코드를 짜다보면 생각치도 못 한 부분에서 오래 걸리는 경우가 있습니다. 보통은 본인의 실력 부족으로 모르고 쓰는 코드에서 문제가 발생하는데요.
이것을 수월하게 확인 할 수 있는 방법이 유니티에서 제공하는 프로파일러 기능입니다.
먼저 유니티 Window탭에서 Profiler를 키면 프로파일러 탭이 뜹니다.
최적화에 관심 있으신 분들은 대부분 아실 기능일텐데 전 이 기능을 팀프로젝트가 다 끝나고나서야 알았습니다...
프로파일러는 유니티 프로그램 구동 시 실시간으로 각종 데이터 사용량을 보여줍니다.
이런식으로 생겼고 왼쪽에 표시되는 데로 초당 16ms이내로 시간이 소요되는 것을 목표로 해야 60프레임이 나옵니다.
CPU, GPU, 메모리, 오디오 등 구분도 잘 되어있는데 보통 가장 많이 보게되는 부분은 아무래도 CPU입니다.
저도 최근에 알아서 항목들을 공부 중인데
일반적인 코드의 경우 WaitForTargetFPS와 Gfx.WaitForPresent가 제일 먼저 눈에 들어옵니다.
위 이미지의 경우에도 노란 영역은 전부 WaitForTargetFPS이며 가끔씩 툭툭 튀는 프레임이 존재하는데 그 부분을 확인해보면 Gfx.WaitForPresent가 자리하고 있습니다.
처음 봤을 땐 도대체 저 둘이 무엇인지 몰랐고 검색해도 바로 만족할만한 해답 글이 뜨지 않아 한참을 고민했는데 계속 알아본 결과 드디어 답을 찾았습니다.
WaitForTargetFPS의 경우 검색해보면 동기화와 관련되어 글들이 뜹니다.
퀄리티 세팅에서 V sync Count(수직동기화)를 키면 발생한다고 하는데 문제는 저는 키지도 않았는데 위와 같이 뜹니다.
하지만 위 프로파일러 이미지에서 볼 수 있듯 노란색은 VSync 를 뜻하고 있어 동기화와 관련이 있음은 명백했습니다.
그렇다면 내가 무슨 짓을 했길래 프로파일러는 나에게 저런 무지막지한걸 보여주는걸까.
먼저 답은 동기화 대기 시간이 맞습니다.
게임 실행 후 게임뷰에서 Stats 창을 보면 60프레임 근처에서 놀고 있는 것을 볼 수 있는데 그 60프레임을 만들어주기 위해 그냥 대기하는 시간입니다.
만약 Application.targetFrameRate 같은 걸로 목표 프레임을 조정하면 그에 맞춰서 저 수치가 바뀌는 것을 확인 할 수 있습니다.
아마 아무 값도 설정해 주지 않으면 기본 60프레임을 노리도록 되어있는거 같은데 팀프로젝트 도중에 일부 컴퓨터에선 설정하지도 않았는데 3천 프레임을 찍는 모습도 봤기에 정확하게는 모르겠습니다.
그다음 Gfx.WaitForPresent의 경우입니다.
얘는 답부터 말하면 GPU의 소요 시간이 CPU를 넘겨버리면 CPU는 GPU가 끝날때까지 대기하는데 그 때 발생하는 시간이라고 합니다.
근데 문제는 제 컴에서는 프로파일러에서 GPU 정보가 뜨지 않아 어느 상황에 GPU가 왜 더 오래 걸려 이런 문제를 발생시키는지 알 수가 없었습니다.
당장은 저게 무엇을 뜻하는지를 아는게 전부네요.
프로파일러에는 이외에도 다양하게 뜨는데 대부분 직관적인 이름들이라 어디가 문제점인지 쉽게 파악할 수 있습니다.
그리고 가비지 발생량도 확인 할 수 있어 어디에서 가비지가 많이 발생하는지도 알 수 있습니다.
프로파일러를 계속 보고있으면 가비지 콜렉터가 실행될 때도 그래프가 튀는걸 볼 수 있는데 이걸 최소화 하기 위해서라도 가비지는 계속 줄여나가야 할 거 같습니다.
'그외' 카테고리의 다른 글
Seoul VR∙AR EXPO 2018 후기(사진 스압) (0) | 2018.04.21 |
---|---|
후처리 외곽선 도전중 (0) | 2018.04.21 |
국비 학원에서 만든 콘솔 슈팅게임 (0) | 2018.03.23 |
포트폴리오 (0) | 2018.01.11 |
배운것들 정리 (0) | 2017.12.05 |