[펌] 유니티 최적화 테크닉 총정리
Unity3D/Tips / 2014. 12. 9. 13:04
- 1. Unity 엔진 최적화 테크닉 총정리 http://cafe.naver.com/devrookie 2014.12.08
- 2. 1. 스크립트 최적화 2. 리소스 최적화 3. 그래픽스 최적화 4. 물리 엔진 최적화 5. 기타
- 3. 들어가기에 앞서 본 내용은 인터넷에 공개된 다양한 참고 자료들을 바탕으로 작성 되었습니다. 유니티의 버전업에 따라서 본내용이 다를 수도 있습니다. (ex. Unity 5.x) 보다 자세한 내용은 마지막 참고자료 링크를 참조해 주세요.
- 4. 병목지점을 파악하라
- 5. 5 최적화의 시작은 병목 파악부터 CPU • 너무 많은 DP CALL • 복잡한 스크립트나 물리 연산 Vertex Processing • 너무 많은 버텍스들 • 버텍스당 너무 많은 연산 (버텍스 셰이더) Fragment Processing • 너무 많은 픽셀, 오버 드로우(OverDraw) • 프래그먼트당 너무 많은 연산 (프래그먼트 셰이더/픽셀 셰이더) Band Width • 크고, 압축되지 않은 텍스쳐 • 고해상도 프레임 버퍼
- 6. 스크립트 최적화
- 7. 7 스크립트 최적화 (1) • 유니티의 핵심 기능은 모두 C++로 제작되어 있다 • 예) Transform.position 에서 Transform은 C# 속성, position은 C++ 영역 • 유니티 객체들을 변수에 저장해서, 캐싱해서 사용하는것이 좋다. • FindObject 계열 함수들은 매우 느리다. (미리 찾아서 캐싱) • Instanitate 와 Destory 함수를 이용한 프리팹의 생성/해제는 비용이 크다 • 활성화/비활성화를 활용 -> 오브젝트 풀링 • Update 함수보다는 CoRoutine을 활용한다. • 나눗셈 보다는 곱셈이 몇 십 배 빠르다.
- 8. 8 스크립트 최적화 (2) • 박싱과 언박싱은 부하가 큰 작업이다 • 나눗셈보다는 곱셈이 몇십배 빠르다 • magnitude 보다는 sqrMagnitude를 사용해서 비교한다. (제곱근 계산 x) • 삼각함수의 값은 상수로 저장하고, 사용하는 것이 좋다. • 문자열은 readonly 혹은 const 키워드를 사용하여, 가비지 컬렉션으로부터 벗어나도록 한다.
- 9. 9 만흉의 원인 : 가비지 컬렉터 가비지 컬렉터(GC)는 언제 일어날지 모른다. • Mono의 동적 메모리 관리 때문에, 메모리 해제를 위해 GC가 자동 호출 된다. • GC는 언제 일어날지 모른다. • GC가 일어나면, 게임이 멈추는 현상(랙)이 발생하게 된다. • 동적 메모리 해제가 가능한 일어나지 않도록 하는것이 GC 관리의 핵심 오브젝트 풀링 • 오브젝트(or 프리팹)의 동적 생성과 해제는 부하가 크다. • 오브젝트가 해제되면, 언젠가는 GC가 동작하여 정리 한다 = 랙이 발생 • 오브젝트를 풀을 만들어 미리 많이 만들어 두고, 활성화/비활성화로 사용한다. • 풀에서 가져와서 사용하고, 사용이 끝나면 비활성화 상태로 풀에 반환 • 오브젝트 풀링 사용은 선택이 아닌 필수!!
- 10. 10 GC에게 먹이 주지 않기 문자열 병합은 StringBuilder • 일반 String + String을 쓰면 임시 문자열이 생성됨 • StringBuilder.Append() 함수를 사용하여 병합 foreach 대신에 for문 사용 • 일반 array에 한해서… • Foreach는 한번 돌때마다 24byte의 쓰레기 메모리를 생성 • 10번만 돌아도 240byte의 GC 수거 메모리를 남김 태그 비교에는 compareTag() 사용 • If(go.tag == “enemy”) 대신에 go.compareTag(“enemy”) 사용 • 객체의 tag 프로퍼티를 호출하는것은 추가 메모리를 할당하고, 복사
- 11. 11 GC에게 먹이 주지 않기 (2) 데이터 타입에는 Class 대신 구조체 사용 • 구조체는 GC에 들어가지 않는다. Stack에 할당 즉시 해제할 때는 Dispose 수동 호출 • 오브젝트의 dispose를 수동으로 호출하여, 즉시 cleanup 임시 객체들을 만들어내는 API들을 조심 • Ex. GetComponents<T>, Mesh.Vertices, Camra.allCameras, etc…
- 12. 12 C++ <-> C# 오버 헤드 객체의 변경 사항을 캐싱 • 객체의 이동과 변형에 대한 처리를 캐싱하고, 매프레임에서 딱 한번만 처리한다. • Ex. Move() 컴포넌트 참조를 캐싱 • Getcomponent()는 한번만 호출하여, 객체를 캐싱해두고 사용 한다. 빈 콜백 함수는 제거 • Start()나 Update() 같은 콜백함수는 비어있어도, 성능에 영향을 끼친다.
- 13. 리소스 최적화
- 14. 14 권장 압축 텍스쳐 사용하기 • 아이폰(PowerVR) : PVRCT • 안드로이드(Tegra) : DXT • 안드로이드(Adreno) : ATC • 안드로이드(공통) : ETC1
- 15. 15 텍스쳐 • 텍스쳐 사이즈는 무조건 2의 제곱이어야 한다. • POT(Power of Two) • POT가 아닌경우 POT 텍스쳐로 변환되어 로딩 된다. • 900 x 900 -> 실제로는 1024 X 1024로 변환 • 텍스쳐 아틀라스를 활용 하라. • 텍스쳐 아틀라스로 최대한 묶음 • UI 만이 아니라, 같은 재질의 오브젝트들을 묶음
- 16. 16 텍스쳐 • 압축된 텍스쳐와 밉맵을 사용하자. (대역폭 최적화) • 32bit가 아닌 16bit 텍스쳐 사용도 상황에 맞게 고려
- 17. 텍스쳐 메모리 사용량 프로파일링 17 //로그를 서버에 남기면 프로파일링에 도움이 된다
- 18. 18 Mesh Import시에 언제나 “Optimize Mesh” 옵션 사용 • 변환 전/변환 후 버텍스 캐쉬를 최적화 해준다 언제나 Optimize Mesh Data 옵션을 사용한다 • Player Setting > Other Settings • 사용하지 않는 버텍스 정보들을 줄여 준다(tangents, Normal, color, etc…)
- 19. 19 오디오 • 모바일에서 스테레오는 의미 없다. • 모두 92kb, 모노로 인코딩 • 사운드 파일을 임포트하면 디폴트로 3D 사운드로 설정 • 2D 사운드로 변경 • 압축 사운드(mp3, ogg), 비압축 사운드(wav) 구별 • 비압축 사운드 : 순간적인 효과음, 이펙트 등 • 압축 사운드 : 배경 음악
- 20. 20 폰트 리소스 최적화 NDC2013 - ‘갤럭시S1’ 에서 풀프레임 퍼즐주주 만들기
- 21. 21
- 22. 22 메모리 용량을 ¼로 절약
- 23. 23 NDC2013 - ‘갤럭시S1’ 에서 풀프레임 퍼즐주주 만들기
- 24. 24 리소스 기타 ResourceLoadAsync() 함수는 엄청 느리다 • 게임 레벨 로드시에 사용했을 경우, 일반 함수에 비해 수십배나 느렸다.
- 25. 그래픽스 최적화
- 26. 26 Culling 프러스텀(Frustum) 컬링 • 각 Layer 별로 컬링 거리를 설정하는 것이 가능하다!! • 멀리 보이는 중요한 오브젝트(ex. 성, 산맥...)은 거리를 멀게 설정하고, 중요도가 낮은 풀이나 나무등은 컬링 거리를 짧게 설정
- 27. 27 Culling 오클루젼(Occlusion) 컬링 • Window->Occlusion Culling 메뉴에서 설정 가능
- 28. 28 오브젝트 통합(Combine) • 드로우콜은 오즈젝트에 설정된 재질의 셰이더 패스당 하나씩 일어난다. • 렌더러에 사용된 재질의 수만큼 드로우 콜이 발생 Combine (통합) • 성질이 동일한 오브젝트들은 하나의 메쉬와 재질을 사용하도록 통합 • Script 패키지 – CombineChildren 컴포넌트 제공 • 하위 오브젝트를 모두 하나로 통합 • 통합하는 경우 텍스쳐는 하나로 합쳐서, Texture Atlas를 사용해야 된다.
- 29. 29 Batch Static Batch • Edit > Project Setting > Player 에서 설정 • 움직이지 않는 오브젝트들은 static으로 설정해서, 배칭이 되게 한다. • Static으로 설정된 게임 오브젝트에서 동일한 재질을 사용 할 경우, 자동으로 통합 • 통합되는 오브젝트를 모두 하나의 커다란 메쉬로 만들어서 따로 저장(메모리 사용량 증가) Dynamic Batch • 움직이는 물체를 대상으로 동일한 재질을 사용하는 경우, 자동으로 통합 • 동적 배칭은 계산량이 많으므로, 정점이 900개 미만인 오브젝트만 대상이 됨
- 30. 30 라이팅 라이트 맵을 사용하자 • 고정된 라이트와 오브젝트의 경우(배경) 라이트 맵을 최대한 활용 한다. • 아주 빠르게 실행된다 (Per-Pixel Light 보다 2~3배) • 더 좋은 결과를 얻을 수 있는 GI와 Light Mapper를 사용할 수 있다. 라이트 렌더 모드 • 라이팅 별로 Render Mode : Important / Not Important 설정 가능 • 게임에서 중요한 동적 라이팅만 Important로 설정 (Per-Pixel Light) • 그렇지 않은 라이트들은 Not Important로 설정
- 31. 31 Overdraw 화면의 한 픽셀에 두번 이상 그리게 되는 경우 (Fill rate) • DP Call의 문제만큼이나, Overdraw로 인한 프레임 저하도 중요한 문제 • 특히 2D 게임에서는 DP Call 보다 더욱 큰 문제가 된다. 기본적으로 앞에서 뒤로 그린다 • Depth testing으로 인해서 오버드로우를 방지 한다 • 하지만 알파 블렌딩이 있는 오브젝트의 경우에는 알파 소팅 문제가 발생 반투명 오브젝트의 개수의 제한을 건다 • 반투명 오브젝트는 뒤에서부터 앞으로 그려야 한다. -> Overdraw 증가 • 반투명 오브젝의 지나친 사용에는 주의해야 한다
- 32. 32 Overdraw (2) 유티니의 Render Mode를 통한 overdraw 확인 가능
- 33. 33 유니티 셰이더 기본 셰이더는 모바일용 셰이더 사용 • 기본 셰이더를 사용할 경우, 모바일용 셰이더를 사용. • Mobile > VertexLit은 가장 빠른 셰이더 복잡한 수학 연산 • pow, exp, log, cos, sin, tan 같은 수학 함수들은 고비용이다. • 픽셀별 그런 연산을 하나 이상 사용하지 않는 것이 좋다. • 텍스쳐 룩업테이블을 만들어서 사용하는 방법도 좋다. • 알파 테스트 연산(discard)는 느리다. • 기본적인 연산보다는 최적화 시키고 간략화시킨 공식들을 찾아서 사용할 수 있다
- 34. 34 유니티 셰이더 (2) 실수 연산 • float : 32bit - 버텍스 변환에 사용. 아주 느린 성능 (픽셸 셰이더에서 사용은 피함) • Half : 16bit – 텍스쳐 uv에 적합. 대략 2배 빠름 • fixed : 10bit – 컬러, 라이트 계산과 같은 고성능 연산에 적합. 대략 4배 빠름 라이트 맵을 사용하자 • 고정된 라이트와 오브젝트의 경우(배경) 라이트 맵을 최대한 활용 한다. • 아주 빠르게 실행된다 (Per-Pixel Light 보다 2~3배) • 더 좋은 결과를 얻을 수 있는 GI와 Light Mapper를 사용할 수 있다.
- 35. 물리엔진 최적화
- 36. 36 Fixed Update 주기 조절 • FixedUpdate()는 Update와 별도로 주기적으로 불리며, 주로 물리 엔진 처리 • 디폴트는 0.02초. 즉 1초에 50번이나 호출됨 • TimeManager에서 수정 가능 • 게임에 따라, 0.2초 정도(혹은 이상)로 수정해도 문제 없음
- 37. 37 물리 엔진 설정 Static Object • 움직이지 않는 배경 물체는, static으로 설정 충돌체의 이동 • 리지드 바디가 없는 고정 충돌체를 움직이면, CPU 부하 발생 • 이럴 경우 리지드 바디를 추가하고, IsKinematic 옵션 사용 Maximum Allowed timestep 조정 • 시스템에 부하가 걸려, 지정되 시간보다 오래 걸릴 경우, 물리 계산을 건너뛰는 설정
- 38. 38 물리 엔진 설정 (2) Solver Iteration Count 조정 • 물리 관련 계산을 얼마나 정교하게 할지를 지정. (높을수록 정교) • Edit > Project Setting > Physics Sleep 조절 • 리지드 바디의 속력이 설정된 값보다 작을 경우, 휴면상태에 들어감 • Physics.Sleep() 함수를 이용하면, 강제 휴면 상태를 만들 수 있음
- 39. 39 물리 엔진 스크립트 래그돌 사용 최소화 • 랙돌은 물리 시뮬레이션 루프의 영역이 아니기 때문에, 꼭 필요할때만 활성화 한다 태그 대신 레이어 • 물리 처리에서 레이어가 훨씬 유리. 성능과 메모리에서 장점을 가진다 메쉬 콜라이더는 절대 사용하지 않는다. 레이캐스트와 Sphere Check 같은 충돌 감지 요소를 최소화
- 40. 40 Tilemap Collision Mesh 2D 게임에서 타일맵의 Collison Mesh를 최적화하라 • Tilemap을 디폴트로 사용해서, 각 타일별로 충돌 메쉬가 있는 경우, 물리 부하가 커진다 • 연결된 Tilemap을 하나의 Collision Mesh로 물리 연산을 최적화 하라
- 41. 참고 자료 • Unity 3D 최적화 http://www.uzoo.in/?mid=master_codesnippet&order_type=desc&document_srl=539&listStyle=viewer • 유니티3D 게임 리소스 최적화? 3가지만 기억해라 HTTP://TECHHOLIC.CO.KR/ARCHIVES/17907 • Optimizing Graphics Performance on Unity : 유니티에서 그래픽 성능 최적화 하기 http://smilemugi.net/wordpress/archives/227 • "14일만에 0에서 60프레임 만들기" Unity3D를 사용하여 우리의 게임을 최적화시키면서 배웠던 것들 • 유니티가 당신에게 알려주지 않는 것들 http://www.slideshare.net/MrDustinLee/ss-27739454?related=3 • NDC2013 - ‘갤럭시S1’ 에서 풀프레임 퍼즐주주 만들기 http://www.slideshare.net/olambdao/unity3d-2d-20130424?related=1 • Unite 2013 optimizing unity games for mobile platforms http://www.slideshare.net/hnam7/unite-2013-optimizing-unity-games-for-mobile-platforms-37933478 • Optimizing unity games (Google IO 2014) • Unity Internals: Memory and Performance
반응형
'Unity3D > Tips' 카테고리의 다른 글
Unity Platform Defines (0) | 2015.01.28 |
---|---|
[펌] 데이터 패스(Data Path) 정리 (0) | 2015.01.12 |
텍스처, 리소스 메모리 최적화 (0) | 2014.12.02 |
유니티 게임 최적화 성능을 위한 정리 (그래픽과 성능) (0) | 2014.10.17 |
유저 기기 고유 ID(UUID) [SystemInfo.deviceUniqueIdentifier] (2) | 2014.10.07 |