본문 바로가기
Unity3D/Tip

유니티 프로파일러(Profiler)를 이용해 성능 개선하기

by 니키티스 2020. 10. 4.

게임을 만들 때 제일 골치 아픈 것은 최적화이다.

 

최적화가 정말 잘 된 게임, 이른바 갓적화인 게임은 낮은 성능의 컴퓨터로도 아주 섬세한 3D 그래픽을 60 프레임으로 표현할 수 있다. 반대로 최적화가 안 된 게임, 속된 말로 개적화 게임은 아주 단순한 2D 도트 그래픽 게임조차 엔비디아 RTX 그래픽 카드에서 40 프레임이 나오지 않을 수 있다.

 

물론 PUBG 같은 배틀 로얄 장르는 최적화를 잘해도 저사양 컴퓨터에서는 프레임 드롭이 심할 수 있다. 이는 타 장르에 비해 플레이어의 수가 많고 맵이 넓어서 처리해야 할 연산량이 많은 데다가, 실시간으로 게임을 진행하기 때문이다. 이러한 장르적 차이나 게임 시스템 상의 차이로 인해 피치 못하게 성능 저하가 일어나기도 한다.

 

그러나 이렇게 원인을 알 수 있는 문제는 어떻게든 해결하거나 개선할 방법을 찾을 수라도 있다.

정말 문제가 되는 케이스는 '렉은 걸리는데 왜 걸리는지 모르는 경우'이다.

 

아무리 봐도 프레임 드롭이 일어날 구석이 없는데 프레임이 30~40까지 내려가는 것이다.

 

이럴 때 사용할 수 있는 것이 바로 프로파일러(Profiler)이다.

프로파일러는 성능 분석을 위한 도구이다. 이는 프로그램의 시간 복잡도 및 공간 상태(메모리), 함수 호출 주기와 빈도를 측정할 수 있다.

프로파일러를 이용하면 어떤 문제로 인해 프로그램의 성능 저하가 일어났는지를 확인할 수 있다.

 

 

 

해당 포스터에서는 유니티에서 사용할 수 있는 유니티 프로파일러(Unity profiler)를 다룰 것이다.

 

유니티 프로파일러는 게임을 최적화하는 데에 유용하게 사용할 수 있다.

 

프로파일러는 프레임 변화를 한눈에 알아볼 수 있게 해 주는데, 프로파일러 창에서는 스크립트를 실행하거나 렌더링 작업을 수행하는 데에 소요된 시간 등을 보여준다. 종류별로, 작업별로 시간을 모두 분석할 수 있고 가장 시간이 많이 소요되는 작업부터 순서대로 정렬해서 보여준다.

 

한마디로 프로파일러를 이용하면 게임 프레임에 문제가 되는 요소들을 확인할 수 있다는 것이다.

 

유니티 프로파일러에 관한 자세한 정보가 궁금하다면 유니티 공식 문서(https://docs.unity3d.com/kr/2018.4/Manual/ProfilerWindow.html)를 참고하자.

 

 

 

Unity Asset Store에서 Corgi Engine 에셋을 구매하여 만든 2D 플랫포머 게임

 

위의 사진을 잘 보면 2D 플랫포머 게임치고 48 fps라는 저조한 프레임이 나타나고 있다.

 

정확한 상황을 설명하자면, 가운데의 캐릭터는 플레이어 캐릭터이다. 몬스터(파랑 슬라임, 핑크 슬라임)에는 인공지능을 위해 AI 컴포넌트를 몇 개 부착했고, 화면에는 안 나오지만 NPC를 둘 배치한 상황이었다. 몬스터가 한 마리 늘어날 때마다 프레임이 12씩 저하되었다. Scene에는 몬스터가 5마리밖에 없었는데 몬스터가 다 죽고 나면 100 fps가량으로 프레임이 늘어났다. 프레임이 떨어질 만한 요소를 찾을 수가 없는데 프레임이 바닥을 치고 있는 상황이어서 해결하고 싶어도 해결할 수가 없었다.

 

이럴 때 프로파일러를 이용하면 문제를 쉽고 간단하게 찾아낼 수 있다.

 

 

 

프로파일러 위치(2019.4.2f1 기준): Window->Analysis->Profiler

 

위와 같이 클릭해서 들어가면 프로파일러 창이 뜬다. 위 사진은 2019.4.2f1을 기준으로 하므로 위치는 버전에 따라 어느 정도 다를 수 있다. 

 

 

Deep Profiler를 체크 해제하고 실행했을 때. 메뉴는 상단의 툴바에 있음.
Deep Profiler를 체크하고 실행했을 때

 

프로파일러를 사용하려면 Profiler 창 좌측 상단에 있는 빨간 녹화 버튼을 누르면 된다. 해당 상태에서 Scene을 시작하면 Profiler가 자동으로 게임의 다양한 부분에 소요된 실행 시간을 분석해준다. 분석하고 싶은 원하는 지점을 클릭하면 그 프레임에 스크립트 실행, 렌더링, 물리 연산 등에 소요된 시간을 확인할 수 있다. 일반적으로 프레임이 저하되어 peak가 가장 높아지는 지점을 클릭하곤 한다.

 

게임 코드에서 시간이 정확히 어디에서 소요되었는지를 알고 싶을 때에는 세부 프로파일링(Deep Profile)을 켜면 된다. 메뉴 중앙 상단에 Deep Profile 설정이 있는데, 이를 체크하면 모든 스크립트 코드가 프로파일링 된다. Deep Profile은 세부적으로 시간을 확인할 수 있는 대신 오버헤드가 매우 커서 메모리를 많이 잡아먹고 켜져 있는 동안 게임이 훨씬 느려진다.

 

대형 게임에서 세부 프로파일링을 사용하면 메모리 부족 현상이 발생해서 아예 세부 프로파일링을 사용할 수도 없을 수 있다. 이 경우 Profiler.BeginSample, Profiler.EndSample 함수를 이용해서 스크립트 코드 블록을 수동으로 프로파일링 하면 개선할 수 있다고 한다.

 

프로파일러 아래의 Hierarchy의 Overview를 보면 PlayerLoop, EditorLoop, Profiler.CollectEditorStats가 있는데 각각 게임 플레이, 유니티 에디터, 프로파일링에 소요한 시간을 가리킨다. 게임 성능에 영향을 주는 것을 확인하려면 PlayerLoop를 확인하면 된다.

 

 

Profiler 창을 확장하거나 스크롤을 내리면 렌더링 정보, 메모리 상태 등도 함께 확인할 수 있다.
프로파일링으로 확인한 성능 저하 원인 코드

 

잘 보니 빨간 직사각형으로 체크해둔 함수들이 게임 실행 시간의 41.9%를 차지하고 있었다.

이 함수들은 유니티 엔진에 내장된 것이 아니라 별도로 물리 체크를 위해 만든 함수들이다.

 

 

CastRaysBelow(), CastRaysAbove(), CastRaysToTheRight()에서 PlayerPrefs.HasKey()가 문제였다.

 

확인해보니 PlayerPrefs.HasKey()에서 대부분의 시간을 낭비하고 있었다. 해당 코드를 직접 확인해보자.

 

 

문제의 PlayerPrefs.HasKey()

 

문제가 발생한 부분은 바로 위이다.

위 함수는 충돌을 체크하는 Ray를 Gizmos로 그리는 기능을 하는데, 매 프레임 PlayerPrefs.HasKey()를 호출하게 되면서 프레임 드롭이 심해졌다.

 

PlayerPrefs는 플레이 데이터를 저장하거나 불러오는 클래스이고, PlayerPrefs.HasKey()는 데이터를 저장한 파일에 접근해 키가 존재하는지를 확인하는 함수이다. PlayerPrefs는 플레이 데이터에 접근하기 위해 파일을 이용하므로 플레이하는 내내 ~/Library/Preferences 폴더의 파일을 읽고 썼던 것이다.

 

파일 입출력은 한 번 실행하는 데에 시간이 오래 걸리므로 다음과 같이 수정했다.

 

 

수정한 코드

 

Unity Editor를 사용하는 동안 Gizmos는 언제나 보여줘도 문제가 없었다. 그래서 Editor를 사용할 때 true를 반환하여 Gizmos를 언제나 Scene 뷰에 표시하도록 했다.

 

 

해결한 후 Profiler 상태(Others 포함). 하늘색 부분(스크립트)이 확 줄었다.
해결한 후 Profiler 상태(Others 제외)

 

결과를 보면 기존보다 훨씬 스크립트에 의한 부분(하늘색 부분)이 줄었음을 알 수 있다.

 

그런데 여기서 Others를 넣냐 빼냐에 따라 프레임이 천차만별로 나타난다. 유니티 공식 문서에 의하면 Others는 다음과 같다.

Others : 애플리케이션이 코드에 소비하는 시간으로, 다른 카테고리에 속하지 않습니다. 여기에는 전체 EditorLoop, 또는 에디터의 플레이 모드에서 프로파일링 시 프로파일링 오버헤드 등의 영역이 포함됩니다.
https://docs.unity3d.com/kr/2019.3/Manual/ProfilerCPU.html
 

CPU 사용 프로파일러 모듈 - Unity 매뉴얼

CPU 사용 프로파일러 모듈은 애플리케이션에서 시간을 소비한 위치를 표시하는 차트를 제공합니다. 이 모듈은 애플리케이션이 시간을 소비하는 모든 주요 영역(예: 렌더링, 스크립트, 애니메이��

docs.unity3d.com

간단히 말해서 Others는 유니티 에디터로 인해 소비되는 시간 등을 가리키므로 게임 성능에는 크게 영향을 미치지 않는다.

 

개선 후 프레임: 169 fps

개선 후 프레임은 훨씬 더 높아졌음을 볼 수 있다.

 

 

이처럼 유니티 프로파일러를 이용하면 최적화를 방해하는 요소를 쉽게 찾을 수 있다.

물론 프로파일러를 보고 수정했을 때 최적화 상태가 더 나빠질 수도 있으니 주의해야 한다.

 

 

 

 

 

 

 

 

 

 

참고 문헌

https://docs.unity3d.com/kr/2018.4/Manual/Profiler.html, 프로파일러 개요 (2020년 10월 4일 접근함)

 

프로파일러 개요 - Unity 매뉴얼

Unity 프로파일러 창은 게임을 최적화하는 데 유용합니다. 이 창에는 게임의 다양한 부분에 소요된 시간이 보고됩니다. 예를 들어 게임 로직 렌더링 및 애니메이션화에 소요되거나 게임 로직에 ��

docs.unity3d.com

https://docs.unity3d.com/kr/2018.4/Manual/ProfilerWindow.html, 프로파일러 창 (2020년 10월 4일 접근함)

 

프로파일러 창 - Unity 매뉴얼

Unity 에디터에서 툴바를 통해 프로파일러 창에 액세스합니다. Window > Analysis > Profiler.

docs.unity3d.com

youtu.be/fROTtgZK-Zs, Unity 101 - Using the Unity Profiler to optimize performance (accessed October 4, 2020)

 

https://docs.unity3d.com/ScriptReference/PlayerPrefs.html, PlayerPrefs (accessed October 4, 2020)

 

Unity - Scripting API: PlayerPrefs

Editor/Standalone On macOS PlayerPrefs are stored in ~/Library/Preferences folder, in a file named unity.[company name].[product name].plist, where company and product names are the names set up in Project Settings. The same .plist file is used for both Pr

docs.unity3d.com

 

댓글