유니티/최적화

[유니티 최적화] 유니티 최적화

코더 제로 2020. 2. 26. 00:48
728x90
반응형

1. 유니티 에디터 

 

 (1) 프로파일링

  Window > Analysis > Profiler 으로 프로파일러로 성능 분석을 합니다.

 

 (2) 배칭(Batch)

  Project Setting > Player > Other Settings 

  - 동적 배칭 : 메시가 충분히 작은 경우 이 기법을 사용하면 메시의 버텍스가 CPU에서 트랜스폼되고, 

   여러 유사한 메시가 그룹화되고, 모든 것이 한꺼번에 드로우됩니다.
  - 정적 배칭: 정적인(움직이지 않는) 게임 오브젝트를 큰 메시로 합치고 더 빠른 방법으로 렌더링합니다.

  움직이지 않는 오브젝트들은 Inspector(인스펙트) 창에서 Static으로 설정해서 배칭이 되게 합니다.

  

 (3) 라이트 맵(LIght Map)

  - 라이트 맵 생성

   Window > Rendering > Lighting > Mixed Lgihting > Baked Gloable Illumination 

  Lighting창의 맨 아래 Generate Lighting 클릭

 

  - 라이트 맵 적용

   Hierarchy(하이아카) 창의 Light 게임오브젝트 > Inspector(인스펙트) 창에서 > Light > Mode에서 선택

 

 (4) Mesh

  - Import시에 언제나 "Optimize Mesh" 옵션 사용합니다. → 기본 옵션

  - Player Setting -> Other Settings : Optimize Mesh Data 옵션을 사용합니다.  → 기본 옵션

 

 (5) 프러스텀(Frustum) 컬링

  -  Layer 별로 컬링 거리를 설정하는 것이 가능합니다.

 

 (6) 오클루젼(Occlusion) 컬링

  - Window > Rendering >  Occlusion Culling 메뉴에서 설정 가능합니다.

  - 카메라에 보이는 각도의 오브젝트들만 렌더링하는 기법.

 

 (7) 오브젝트 통합 (Combine)

  - 드로우 콜은 오브젝트에 설정된 재질의 셰이더 패스당 하나씩 일어납니다.

  - 렌더러에 사용된 재질의 수만큼 드로우 콜이 발생합니다.

 

 (8) 오버드로우(Overdraw)

  - 화면의 한 픽셀에 두 번 이상 그리게 되는 경우 프레임 저하도 중요한 문제입니다.  

  - 오버드로우를 줄이는 방법은 큰 영역을 차지하는 물체를 먼저 그리면 됩니다.

  - 기본적으로 앞에서 뒤로 그립니다.

    Depth testing으로 인해 오버드로우를 방지합니다.

    하지만 알파 블렌딩이 있는 오브젝트의 경우에는 알파 소팅 문제가 발생합니다.

 - 반투명 오브젝트의 개수의 제한을 겁니다.

   반투명 오브젝트는 뒤에서부터 앞으로 그려야합니다. -> Overdraw 증가

   반투명 오브젝트의 지나친 사용에는 주의해야합니다.

  - 유니티 Canvas > Render Mode를 통해 overdraw 확인이 가능합니다.

 

 (9) 물리 엔진 설정

  - Static : 움직이지 않는 게임 오브젝트 인스펙트 창에 Static을 활성화 합니다.

  - 충돌체의 이동

   리지드 바디가 없는 고정 충돌체를 움직이면 CPU 부하가 발생합니다 

   이럴 경우에 리지드 바디를 추가하고 IsKinematic 옵션을 사용합니다.

  - Edit > Project Settings > Time > Maximum Allowed timestep 조정

   시스템에 부하가 걸려 지정된 시간보다 오래 걸릴 경우, 물리 계산을 건너 뛰는 설정합니다.

  - Edit > Project Setting > Physics > Default Solver Iteration

   물리 관련 계산을 얼마나 정교하게 할지를 지정합니다. (높을수록 정교함)

  - 물리엔진 최적화 : Fixed Update 주기 조절

   FixedUpdate() Update와 별도로 주기적으로 불리며, 주로 물리 엔진 처리

   디폴트는 0.02,  1초에 50번 호출합니다.

   Edit > Project Settings > Time에서 수정이 가능합니다

   게임에 따라 0.2초 정도(혹은 이상)로 수정해도 문제 없습니다.

 - Sleep 조절

  리지드바디의 속력이 설정된 값보다 작을 경우 휴면 상태에 들어갑니다.

  Physics.Sleep() 함수를 이용하면 강제 휴면 상태를 만들 수 있습니다.

 - 래그돌 사용을 최소화합니다.

  랙돌은 물리 시뮬레이션 루프의 영역이 아니기 때문에 꼭 필요할 때만 활성화합니다.

 - 태그 대신 레이어 사용

 - 메쉬 콜라이더는 절대 사용하지 않는다.

 - 레이캐스트와 Sphere Check 같은 충돌 감지 요소를 최소화합니다.

 

 (10) Tilemap Collision Mesh

  2D 게임에서 타일 맵의 Collision Mesh를 최적화하라

  Tilemap을 디폴트로 사용해서 각 타일별로 충돌 메쉬가 있는 경우 물리 부하가 커집니다.

  연결된 Tilemap을 하나의 Collision Mesh로 물리 연산을 최적화 합니다.

 

 (11) 유니티 셰이더

  기본 셰이더는 모바일용 셰이더 사용 : Mobile -> VertexLit은 가장 빠른 셰이더

 

2. 프로그래밍

 (1) 빈 콜백 함수 제거

  사용하지 않는 Start()나 Update() 콜백 함수는 제거합니다.

 

 (2) 유니티 에디트에서만 Debug.Log 사용.

   Debug.Log는 빌드시 제거하거나, 유니티 에디트에서만 로그를 찍는 메서드를 만들어서 사용합니다.

 

DebugLog 
public static void DebugLog(string message)
{
#if UNITY_EDITOR
    Debug.Log(message);
#endif
}

 

 (3) 캐싱(Caching)

  유니티 객체들은 멤버변수에 저장하여, 캐싱을 이용합니다. 

  transform caching : transform에 자주 접근하게 되는 객체에선 caching은 선택이 아닌 필수입니다.

 

캐싱 
private Transform m_PlayerTransform;

void Start()
{
    m_PlayerTransform = transform;
}

 

 

 (4) Find 함수

  FindFind, FindGameObjectsWithTag, FindWithTag 함수는 되도록 사용하지 않거나, Awake, Start에서만 사용합니다.

 

 (5) GetComponent()

  GetComponent()는 한번만 호출하고, 될수 있으면 Awake, Start에서 캐싱을 해 두고 사용합니다.

 

 (6) 오브젝트 풀링(Object Pooling

  Instantiate, Destroy 메서드는 될 수 있으면 사용하지 않고, 미리 오브젝트를 할당 해 두었다고 SetActive 메서드를 이용하여 On/Off를 합니다.

  단, 총알이나 미사일의 경우에는 Instantiate, Destroy 메서드를 사용 할 수 밖에 없습니다.

 

 (7) 코루틴(Coroutine)

  업데이트(Update) 메시지 보다는 코루틴(Coroutine)를 사용합니다.

 

 (8) 곱하기

나눗셈 중 일부는 곱셈으로 변환이 가능한 연산이 있습니다.

변환이 가능하면 곱셈을 사용합니다.

 

곱하기 나누기
x / 10 x * 0.1f
x / 8 x * 0.125f
x / 5 x * 0.2f
x / 4 x * 0.25f
x / 2 x * 0.5f

 

 (9) 박싱, 언박싱

  박싱과 언박싱은 사용하지 않습니다.

 

  박싱 : object형 변수에 다른 데이터 형식에 값을 대입하는 것입니다.

 

예제 : 박싱
int i = 123;
object o = i; // boxing

 

  언박싱 : 일반 데이터 형식 변수에 object형 값을 대입하는 것입니다.

 

예제 : 언박싱
object o = 123;
int i = (int)o; // unboxing

 

 (10) sqrMagnitude
  Magnitude 보다 sqrMagnitude를 사용합니다.

   

 (11) 수학상수 
  수학상수나 삼각함수의 값은 상수로 저장하고 사용합니다.

 

수학상수
public const double Pi = 3.14159;
public const double E = 2.71828;

 

 (12) 상수 한정자

  상수로 사용하는 문자열은 readonly 혹은 const 키워드를 사용합니다.

 

 (13) StringBuilder

  문자열 병합은 StringBuilder의 Append를 사용합니다.

 

 (14) for문

  foreach 대신에 for를 이용합니다.

 

 (15) CompareTag() 
  태그 비교는  CompareTag 메서드를 사용합니다.

  go.CompareTag("Player")

 

 (16) 객체의 변경 사항을 캐싱
  객체의 이동(transform.position, transform.rotation)과 변형(transform.localScale)에 대한 처리를 캐싱하고, 매프레임에서 딱 한번만 처리합니다.

 

 (17) Equals 메서드

  비교문에서 == 비교는 Equals 메세드를 사용합니다.

 

 (18) Struct 
  데이터 타입 중 멤버변수가 적으면(2~4), Class 대신 Struct 를 사용합니다.

 

 (19) 배열

  다차원 배열보다는 가변 배열, 가변 배열보다는 일차원 배열을 사용합니다.

  일차원 배열 > 가변 배열 > 다차원 배열

 

 (20) Dispose
  즉시 해제할 때는, Dispose 메서드를 호출합니다.

using UnityEngine; 

public class DisposeExample : MonoBehaviour 
{ 
    Renderer m_Renderer; 

    IEnumerator Start() 
    { 
        m_Renderer = GetComponent(); 

        WWW www = new WWW("https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png"); 
        yield return www; 
        m_Renderer.material.SetTexture("_MainTex", www.texture); 
        www.Dispose(); 
    } 
}

 

Dispose 메서드도 있지만 using 문을 사용하면 using 문 끝나면 자동적으로 Dispose 됩니다.

using System.Collections; 
using UnityEngine; 

public class UsingExample : MonoBehaviour 
{ 
    Renderer m_Renderer; 

    IEnumerator Start() 
    { 
        m_Renderer = GetComponent(); 

        using (WWW www 
                    = new WWW("https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png")) 
        { 
            yield return www; 
            m_Renderer.material.SetTexture("_MainTex", www.texture); 
        } 
    } 
}

 

 (22) LINQ 명령어를 사용하지 않는 것이 좋습니다.

 

 (21) 임시 객체를 만들어내는 메소드( GetComponents, Mesh, Vertices, Camera.allCameras 등)를 조심하게 사용해야 합니다.

 

 (22) ResourceLoadAsync()  메소드는 엄청 느립니다.

 

 (23) 빈 delegate를 작성하지 말아야 합니다.

 

 (24) Parse

 string -> int tryParse를 사용합니다.

 

3. 텍스처

 (1) POT(Power of Two)

  텍스처 사이즈는 2의 제곱이여야 합니다. 

  512 x 512, 1024 x 1024 등 ...

 

 (2) 아틀라스(Atlas)

  - 텍스쳐 아틀라스를 사용합니다.

  - 한 화면에 나오는 텍스쳐끼리 묶어서 아틀라스를 만듭니다.

  - 알파가 있는 텍스쳐끼리, 알파가 없는 텍스쳐끼리 묶습니다.

  - 압축된 텍스처와 밉맵을 사용하자. (대역폭 최적화)

  - 알파값이 없으면 16 bit 텍스쳐를 사용합니다.

 

 (3) 권장 압축 텍스처

  - 아이폰(PowerVR) : PVRCT
  - 안드로이드(Tegra) : DXT
  - 안드로이드(Adreno) : ATC
  - 안드로이드(공통) : ETC1

 

4. 오디오

 (1) 모바일에서 스트레오는 의미 없습니다.   모두 92kb, 모노로 인코딩

 (2) 압축 사운드 (mp3, ogg), 비압축 사운드 (wav) 구별

  - 비압축 사운드 : 순간적인 효과음, 이펙트 등..

  - 압축 사운드 : 배경 음악

 

출처 : https://www.slideshare.net/agebreak/unite2015-47100325

 

 

 

728x90
반응형