[Unity]모바일 게임 성능 최적화 중국어 버전

앞부분에 썼는데 제 능력이 한계가 있어서 훑어보고 가볍게 뿌렸습니다. 관심이 있고 능력이 있는 학생들은 영어 원본을 읽는 것이 좋습니다.

원본 링크

추출 코드: p9fu

참고: 노란색으로 표시된 부분은 능력의 한계로 번역하기 어려운 부분이므로 영문 원문을 참고하시면 이해하실 수 있습니다.

그런데 불만 사항: 블로그 게시 페이지에서 워드 문서 전체를 직접 복사하면 사진이 항상 "업로드 중..." 상태에서 멈춰서 하나씩만 복사할 수 있습니다.


프로파일링 _ _ _

Unity 에는 다음과 같은 도구가 제공됩니다.

프로파일러

프로파일러를 켜고 런타임에 프로파일러를 실행합니다.

빌드 시 Development.Build, Autoconnect.Profiler를 확인하세요.

특정 장면의 프레임 수를 수정합니다.

Unity>기본 설정>분석>프로파일러>프레임 수 

기본값은 300이며, 다양한 디버깅 최적화 시나리오에 적용하기 위해 최대 2000까지 늘릴 수 있습니다. (동시에 값이 높을수록 CPU와 메모리를 더 많이 소모합니다.) 

프로파일러 보기:

계층 

경과 시간을 기준으로 샘플 정렬을 지원합니다. 동시에 현재 프레임 및 관리되는 힙 메모리(GC.Alloc)의 함수 호출 수를 계산할 수도 있습니다.

타임라인 

특정 프레임 시간의 시각적 분석을 보여줍니다. 시각화는 다양한 활성 프로세스와 스레드 간의 상관 관계를 보여줍니다. 이를 사용하여 CPU 바인딩인지 GPU 바인딩인지 확인합니다.

프로젝트 프로파일링을 시작하기 전에 Profiler .data 파일을 저장하세요. 그런 다음 해당 최적화 작업을 수행한 후 수정 전 .data 파일을 수정된 파일(구성-최적화-비교)과 비교합니다. 성능을 최적화하려면 이 과정을 반복하세요.

분석과 최적화는 조기에 자주 이루어져야 합니다.

성능 분석 및 최적화는 가능한 한 빨리 수행되어야 하며, 프로젝트가 온라인화되려고 할 때가 아닌 프로젝트 초기 단계에 문제가 있을 때 항상 수행되어야 합니다.

맹목적으로 최적화하지 마세요

게임 성능이 xx가지 이유에 의해 영향을 받는다고 추측하거나 추측하지 말고, Unity 프로파일러와 해당 플랫폼의 성능 분석 도구를 적시에 사용하여 성능 저하 문제의 원인을 정확하게 찾아내고 찾으십시오.

대상 장치의 프로필 

Unity 프로파일러는 모바일 플랫폼 엔진의 모든 부분을 수집할 수 없지만 iOS와 Android에는 자체 플랫폼에 맞는 성능 최적화 도구가 있습니다.

iOS: Xcode/Instruments
Android: Android Studio/Android 프로파일러 

일부 플랫폼에 고유한 성능 분석 도구:

比如,Arm Mobile Studio,Intel VTune,Snapdragon Profiler。

프로필 분석기 

이 도구는 여러 프로파일러에서 데이터를 수집한 다음 최적화 전후의 데이터를 비교하고 찾아 관심 있는 특정 프레임을 분석하고 최적화할 수 있습니다. Profiler의 보완 및 확장 기능으로, 더 자세한 프레임 데이터를 볼 수 있습니다. 이 도구는 Unity의 패키지 관리자에서 사용할 수 있습니다.

프레임당 특별 시간 예산

이론적으로 30fps(초당 프레임 수)의 각 프레임은 33.33ms(1000ms/30fps)가 소요됩니다. 60fps는 프레임당 16.66ms가 소요됩니다.

그러나 모바일 플랫폼에서는 이 시간을 항상 사용할 수 없습니다. 장치가 과열되고 CPU 및 GPU의 클럭이 느려질 수 있기 때문입니다.

GPU 바인딩인지 CPU 바인딩인지 확인

Gfx .WaitForCommands 플래그: 렌더링 스레드가 준비되었으며 기본 스레드가 차단되었습니다.

Gfx .WaitForPresent 플래그: 메인 스레드가 준비되었으며 GPU가 차단되었습니다.

기기 온도에 주의하세요

과열은 성능에 직접적인 영향을 미칠 수 있습니다.

저사양 기기에서 성능 테스트

이전 버전과 호환되며 호환 가능한 가장 낮은 대상 장치에서 성능 테스트

권장 관찰 순서: 렌더링 -> 메모리(GC) -> 코드 스크립트


메모리


Unity는 자동 메모리 관리를 사용하여 사용자 생성 코드와 스크립트를 관리합니다. 값 유형의 지역 변수와 같은 더 작은 데이터 청크가 스택에 할당됩니다. 관리되는 힙에 할당되는 더 큰 데이터 블록 및 영구 데이터 스토리지.

GC(가비지 수집기)는 사용되지 않은 힙 메모리를 주기적으로 식별하고 해제합니다. 가비지 수집 작업이 자동으로 실행되면 힙 메모리의 모든 개체가 사용되는지 확인하며, 이 작업으로 인해 게임이 멈추거나 성능이 저하될 수 있습니다.

메모리 사용을 최적화한다는 것은 메모리를 할당하고 해제할 시기를 파악하고 가비지 수집의 영향을 최소화하는 것을 의미합니다.

Unity 관리형 힙 소개를 참조하세요.

유니티 - 매뉴얼: 관리되는 메모리

메모리 프로파일러 스크린샷 비교

메모리 프로파일러 사용

이 별도의 구성 요소는 관리되는 힙 메모리(패키지 관리자에서 미리 보고 다운로드할 수 있음)의 스크린샷을 찍을 수 있어 조각화 및 메모리 누수와 같은 문제를 정확히 찾아내는 데 도움이 됩니다.

트리 맵 보기에서 변수를 클릭하면 메모리에 저장된 로컬 개체를 찾습니다. 여기에서 매우 큰 텍스처나 중복 자산과 같은 일반적인 메모리 소비 문제를 볼 수 있습니다.

메모리 프로파일러를 사용하여 메모리 사용 효율성을 높이는 방법을 알아보세요.

https://www.youtube.com/watch?v=I9wB4Cvgz5g

또는 Unity 공식 문서를 참조하세요.

메모리 프로파일러 | 메모리 프로파일러 | 0.2.10-preview.1
 

GC(가비지 수집)의 영향 감소

Unity는 Boehm-Demers-Weiser 가비지 컬렉터를 사용하여 프로그램 코드 실행을 중지하고 실행이 완료된 후에만 프로그램의 정상적인 작동을 다시 시작합니다. ( 프로그램 코드 실행을 중지하고 작업이 완료된 후에만 정상적인 실행을 재개합니다 )

Bem 가비지 수집기 참조 문서: C 및 C++용 가비지 수집기

GC 스파이크를 일으킬 수 있는 특정 불필요한 힙 할당에 주의하세요.

문자열:

C#에서 문자열 형식은 값 형식이 아닌 참조 형식입니다.

불필요한 문자열 유형 생성 및 작업을 줄입니다.

JSON 및 XML과 같은 문자열 기반 데이터 파일을 구문 분석하지 마세요. ScriptableObjects에 데이터를 저장하거나 JSON 및 XML 대신 MessagePack, Protobuf 및 기타 형식을 사용할 수 있습니다.

Unity 자체 함수 호출:

일부 함수는 힙 할당을 생성합니다.

루프에서 반복적으로 작업하는 대신 배열에 대한 참조를 캐시합니다.

또한, 우리가 원하는 것을 달성하기 위해 기존 방법을 사용해 보십시오. 예를 들어, 문자열을 GameObject.tag와 직접 비교하는 대신 GameObject.CompareTag(string) 메서드를 사용하여 객체의 Tag를 결정합니다(이렇게 하면 새로 생성된 문자열 유형 가비지가 반환되기 때문입니다).

권투:

값 유형 변수와 참조 유형 변수 사이를 전달하지 마세요. 이 작업은 임시 개체를 생성하여 잠재적인 쓰레기를 가져오기 때문입니다. 예를 들어 값 유형을 강제로 객체 유형(int i = 123, 객체 o = i)으로 변환합니다.

코루틴:

Yield는 가비지를 생성하지 않지만 새로운 WaitForSeconds 개체를 생성하면 가비지가 생성됩니다. 따라서 WaitForSeconds 개체가 생성될 때마다 생성하는 대신 캐시하고 재사용해 보세요.

언어 통합 쿼리 및 정규식(LINQ 및 정규식):

성능 문제가 있는 경우 LINQ 및 정규식을 사용하지 않는 것이 좋습니다. 둘 다 최하위 수준에서 박싱 작업을 수행하고 가비지를 생성하기 때문입니다.

가능하다면 정기적으로 쓰레기를 수거하십시오.

특정 시점의 가비지 수집이 게임에 영향을 미치지 않는다고 확신하는 경우 System.GC.Collect를 수동으로 호출하여 가비지 수집을 수행할 수 있습니다. "자동 메모리 관리 이해"를 참조하여 언제 자신에게 유익한 일을 할 수 있는지 알아볼 수 있습니다: https://docs.unity3d.com/Manual/performance-memory-overview.html

증분 GC를 사용하여 가비지 수집 작업 부하 완화 

프로그램 실행을 위해 증분 가비지 수집기는 여러 개이고 차단 시간이 훨씬 짧으며(중단 시간이 훨씬 짧음) 가비지 수집 작업 부하를 완화하기 위해 여러 프레임에 걸쳐 실행을 분산합니다. 단 한번의 긴 중단보다는.

가비지 수집이 애플리케이션 성능에 영향을 미치는 경우 이 옵션을 켜서 가비지 수집 급증을 크게 줄일 수 있는지 확인할 수 있습니다. 프로필 분석기를 사용하면 애플리케이션 성능이 향상되는지 확인할 수 있습니다.

 증분 가비지 수집기를 사용하여 GC 급증을 줄입니다.


적응형 성능

Unity와 Samsung의 적응형 기능을 사용하면 장치의 온도와 배터리 수준을 모니터링하여 문제가 발생하기 전에 적절하게 조정할 수 있습니다. 예를 들어, 사용자가 장시간 플레이하는 경우

그런 다음 게임의 세부 수준(LOD)을 동적으로 낮추어 게임이 원활하게 실행되도록 할 수 있습니다. 적응형 성능을 통해 개발자는 게임 성능을 유지하면서 통제된 방식으로 게임 성능을 향상시킬 수 있습니다.

적응형 성능 관련 API를 통해 애플리케이션을 조정할 수 있으며 일부 자동 모드도 제공합니다. 이러한 모드에서는 적응형 성능이 다음 주요 지표를 통해 게임 설정을 결정합니다.

-이전 프레임을 기준으로 원하는 프레임 속도

-장치 온도 수준

- 열 이벤트에 대한 장치 근접성

- CPU 또는 GPU 바인딩된 장치

이 네 가지 지표 ( 메트릭 ) 는 장치의 상태를 결정합니다 . 적응형 성능은 해당 설정을 조정 하고 최적화하여 성능 병목 현상을 줄입니다 . 이는 장치의 상태를 설명하는 인덱서 (Indexer)라는 정수 값을 제공함으로써 수행됩니다 . (이 네 가지 지표는 장치의 상태를 나타내며 적응형 성능은 조정된 설정을 조정하여 병목 현상을 줄입니다. 이는 장치의 상태를 설명하기 위해 인덱서라고 하는 정수 값을 제공하여 수행됩니다.)

적응형 성능은 삼성 기기만 지원합니다. 

패키지 관리자 > 적응형 성능 > 샘플을 선택하여 패키지 관리자에서 제공하는 예제를 보면 적응형 성능에 대해 자세히 알아볼 수 있습니다. 각 예는 특정 변수(스케일러)의 영향을 받으므로 다양한 변수가 게임에 어떤 영향을 미치는지 확인할 수 있습니다. 또한 적응형 성능 구성과 해당 API를 올바르게 사용하는 방법에 대해 자세히 알아보려면 최종 사용자 설명서를 검토하는 것이 좋습니다.

적응형 성능 샘플 : 

적응형 성능 샘플 사용 | 적응형 성능 | 2.1.1

최종 사용자 문서   

적응형 성능 사용자 가이드 | 적응형 성능 | 2.1.1


프로그래밍 코드 아키텍처

Unity의 PlayerLoop에는 게임 엔진의 핵심과 상호 작용하는 기능이 포함되어 있습니다. 이 트리 구조에는 초기화 관련 프레임별 업데이트를 처리하는 여러 시스템이 포함되어 있습니다. 모든 게임 관련 스크립트의 실행은 PlayerLoop에 따라 다릅니다.

프로파일링 뷰를 보면 프로젝트의 모든 사용자 코드가 PlayerLoop 아래에 있음을 알 수 있습니다(Editor 관련 스크립트는 EditorLoop 아래에 있음).

사용자 스크립트, 설정 및 렌더링 관련 콘텐츠는 각 프레임의 계산과 화면의 최종 렌더링 시간에 큰 영향을 미칠 수 있습니다. 

다음 팁과 요령을 사용하여 스크립트를 최적화할 수 있습니다.

Unity PlayerLoop를 완전히 이해하세요. 

먼저 각 프레임 루프 동안 Unity의 코드가 실행되는 순서를 이해해야 합니다. 각 Unity 스크립트의 일부 기능은 미리 결정된 순서로 실행됩니다. 스크립트의 전체 생성 수명 주기 동안 Awake , Start , Update 및 기타 방법 간의 차이점을 명확하게 이해하고 이해해야 합니다 .

스크립트의 전체 라이프사이클에 걸친 기능 실행 순서에 대해서는 "스크립트 라이프사이클 흐름 차트"를 참조하십시오.

유니티 - 매뉴얼: 이벤트 함수의 실행 순서

매 프레임마다 많은 양의 코드를 실행하지 마세요.

코드 조각이 실제로 매 프레임마다 실행되어야 하는지 여부는 신중하게 고려하고 주의할 가치가 있는 문제입니다. 불필요한 코드는 Update , LateUpdate FiexdUpdate 에서 제거될 수 있습니다 . 프레임마다 실행해야 하는 코드를 이러한 메서드에 넣을 수 있지만 자주 업데이트할 필요가 없는 일부 로직은 넣지 않도록 하세요. 가능하다면 변경 사항이 발생할 때만 해당 로직을 실행하세요.

layerLoop 수명주기 다이어그램

업데이트 기능을 꼭 사용해야 한다면 n 프레임마다 코드를 실행하는 것을 고려해 보세요. 이는 시간 분할을 적용하여 여러 프레임에 걸쳐 코드 작업 부하를 분산시키는 일반적인 기술입니다. 다음 예제에서는 3프레임마다 exampleExpensiveFunction 메서드를 실행합니다.

private int interval = 3;

void Update()

{

    if (Time.frameCount % interval == 0)

    {

          ExampleExpensiveFunction();

    }

}

Start / Awake 기능 에 많은 로직을 작성 하지 마세요.

첫 번째 장면이 로드되면 각 객체에 대해 다음 함수가 호출됩니다.

 깨어

— 켜기 활성화

- 시작

프로그램의 첫 번째 프레임이 렌더링되기 전에 이러한 함수 내에 많은 시간이 소요되는 논리를 작성하지 마십시오. 그렇지 않으면 불필요한 로딩 시간을 많이 소비하게 됩니다.

첫 번째 장면을 로드하는 자세한 과정을 알아보려면 다음 링크를 참조하세요.

유니티 - 매뉴얼: 이벤트 함수의 실행 순서

빈 Unity 메서드 이벤트 방지

빈 MonoBehaviour라도 요청 리소스를 차지하게 되므로 빈 Update나 LateUpdate 및 기타 메서드를 삭제해야 합니다.

이러한 방법을 사용하여 일부 기능을 테스트하려면 전처리기 지시문을 사용하세요.

#if UNITY_EDITOR

Void Update()

{

}

#endif

이 경우 패키징 시 불필요한 비용 걱정 없이 자유롭게 Update를 이용하여 기능을 테스트할 수 있습니다.

디버그 로그 삭제 

로그 수가 많으면(특히 업데이트, LateUpdate 및 FixUpdate에서) 프로그램 성능에 영향을 미칩니다. 불필요한 로그 정보는 패키징하기 전에 비활성화할 수 있습니다.

이 요구 사항은 조건부 속성( Conditional Attribute )과 전처리 지시문을 사용하여 쉽게 달성할 수 있습니다 . 예를 들어 다음과 같이 클래스를 사용자 정의합니다.

public static class Logging

{

  [System Diagnostics Conditional(“ENABLE_LOG”)]

  static public void Log(object message)

  {

      UnityEngine Debug Log(message);

  }
}

 

스크립트를 차별화하기 위해 전처리기 지시문을 추가하세요. 

사용자 정의 클래스를 사용하여 로그를 인쇄하십시오. 모든 로그 정보를 비활성화해야 하는 경우 플레이어 설정에서 이 전처리 명령을 삭제하기만 하면 모든 로그 정보가 몇 분 안에 사라집니다.

문자열 매개변수 대신 해시 값을 사용하세요.

Unity의 하위 레이어는 Animator, Material, Shader 등과 같은 속성을 처리하기 위해 문자열 유형 이름을 사용하지 않습니다. 효율성을 높이기 위해 모든 속성 이름은 실제로 이러한 속성을 처리하는 데 사용되는 해시 ID를 사용합니다.

애니메이터, 머티리얼 또는 셰이더에서 Set 또는 Get 메서드를 사용할 때마다 문자열 매개변수 대신 정수 값을 사용하는 메서드를 사용하세요. 문자 매개변수가 있는 메소드는 문자열 유형을 해시 유형으로 변환한 다음  해시 ID를 정수 매개변수가 있는 메소드에 전달하기 때문입니다 . (문자열 메서드는 단순히 문자열 해싱을 수행한 다음 해시된 ID를 정수 값 메서드로 전달합니다.)

Animator.StringToHash를 사용하여 Animator의 속성 이름을 가져오고 Shader.PropertyToID를 사용하여 머티리얼 볼 또는 셰이더의 속성 이름을 가져옵니다.

올바른 데이터 구조를 선택하세요

매 프레임마다 수만 개의 데이터가 지속적으로 반복되며, 수만 번 반복할 때 선택한 데이터 구조는 성능에 큰 영향을 미칠 수 있습니다. 따라서 컬렉션에서 목록(List), 배열(Array) 또는 사전(Dictionary)을 사용해야 하는지 여부가 특히 중요합니다. C#에서는 데이터 구조에 대한 일반 자습서 MSDN 가이드를 참조하여 자신에게 적합한 올바른 데이터 구조를 선택할 수 있습니다.

런타임 구성요소 추가 방지

런타임에 AddComponent 함수를 호출하면 상당한 소비가 발생합니다. 런타임 시 이 메서드를 언제 호출하든 Unity는 현재 객체에 중복된 구성 요소나 기타 필수 구성 요소가 있는지 확인하기 때문입니다.

일반적으로 필요한 구성 요소를 이미 바인딩한 프리팹을 직접 인스턴스화하면 성능 오버헤드를 더 많이 줄일 수 있습니다.

게임 개체 ( Gameobjects ) 및 구성 요소 ( 구성 요소 ) 캐싱

GameObject .Find , GameObject .GetComponent Camera .main ( 2020.2 이전) 메서드 성능 집약적이므로 Update 에서 이러한 메서드를 호출Start 중에 이러한 메서드를 호출하고 이러한 인스턴스를 캐시할 수 있습니다

예를 들어, 다음은 GetComponent를 반복적으로 호출하는 부정적인 예입니다 .

void Update()
{
 	Renderer myRenderer = GetComponent<Renderer>();
 	ExampleFunction(myRenderer);
}

대신 GetComponent 메서드를 한 번만 호출하고 해당 반환 값을 캐시할 수 있습니다. 그러면 매번 GetComponent 메서드를 호출할 필요 없이 Update 에서 이 반환 값을 재사용 할 수 있습니다.

private Renderer myRenderer;
void Start()
{
 	myRenderer = GetComponent<Renderer>();
}
void Update()
{
 	ExampleFunction(myRenderer);
}

개체 풀 사용

개체 인스턴스화 및 소멸은 가비지를 가져오고 가비지 수집 급증을 생성하는 느린 프로세스인 경우가 많습니다. 객체 풀을 사용하면 이러한 객체(예: 총에서 발사되는 총알)를 자주 인스턴스화하고 파괴하는 대신 재사용하거나 재활용할 수 있는 일부 객체를 미리 로드할 수 있습니다.

이 예에서 객체 풀은 재사용할 수 있는 20개의 PLAyerLaser 인스턴스를 생성합니다.

CPU가 상대적으로 유휴 상태일 때 재사용할 수 있는 일부 인스턴스를 인스턴스화합니다. 그런 다음 이러한 개체는 컬렉션에 저장됩니다. 게임이 실행 중일 때 현재 사용 가능한 개체를 꺼내 활성화하면 됩니다. 필요하지 않으면 비활성화하고 파기하는 대신 개체 풀로 반환합니다.

이렇게 하면 프로젝트에서 관리되는 메모리 할당을 줄여 가비지 수집으로 인한 문제를 피할 수 있습니다.

 개체 풀의 모든 PlayerLaser 개체는 비활성 상태이며 언제든지 방출될 수 있습니다.

이 문서를 참조하여 간단한 개체 풀 시스템을 만드는 방법을 알아볼 수 있습니다.

객체 풀링 소개 - Unity Learn

사용 ScriptableObjects

MonoBehaviours 대신 ScriptableObjects 에 고정 값이나 설정을 저장합니다 . ScriptableObject 는 한 번만 설정하면 되는 프로젝트 내의 자산입니다. GameObject 와 직접 연결할 수 없습니다 .

ScriptableObject 에 필드 를 만들어 값이나 설정을 저장한 다음 MonoBehaviour 에서 참조하세요 .

이 예에서 Inventory라는 ScriptableObject는 다양한 GameObject 설정을 보유하고 있습니다. 

ScriptableObject에서 이러한 필드를 사용하면 Monobehaviour에서 객체를 인스턴스화할 때마다 불필요한 데이터 중복을 피할 수 있습니다.

비디오 튜토리얼 " ScriptableObjects 소개 "를 통해 ScriptableObjects가 프로젝트 최적화에 어떻게 도움이 되는지 알아볼 수 있습니다. 다음 문서를 통해서도 관련 지식을 배울 수 있습니다.

유니티 - 매뉴얼: ScriptableObject


프로젝트 구성

다음 프로젝트 설정은 휴대폰 성능에 영향을 미칩니다.

가속도계 주파수 (Accelerometer Frequency) 를 줄이거나 비활성화합니다.

Unity는 모바일의 가속도계를 초당 여러 번 풀링합니다. 더 나은 성능을 위해 게임에 가속도계가 필요하지 않은 경우 이 속성을 비활성화하거나 빈도를 줄이도록 선택할 수 있습니다.

게임에서 가속도계 주파수를 사용하지 않는 경우 이 속성을 비활성화해야 합니다.

일부 불필요한 플레이어 또는 품질 설정을 비활성화합니다.

너무 많은 셰이더 변형 생성을 줄이려 지원되지 않는 플랫폼에 대해 플레이어 설정 에서 자동 그래픽 API를 비활성화하세요. 애플리케이션이 이전 CPU를 지원하지 않는 경우 대상 아키텍처를 비활성화합니다 . 

품질 설정 에서 필요하지 않은 품질 수준을 비활성화합니다.

불필요한 물리 효과 비활성화 (물리)

게임에 물리적 효과가 필요 하지 않은 경우 자동 시뮬레이션 자동 동기화 변환을 선택 취소하세요 . 이러한 설정은 애플리케이션의 효율성을 감소시켜 득보다 실이 더 많습니다.  

올바른 프레임 속도를 선택하세요

모바일 게임의 프레임 속도는 기기의 전력과 발열 사이에서 균형을 이루거나 균형을 이루어야 합니다. 절충안으로 게임을 60fps 대신 30fps로 제한하는 것을 고려할 수 있습니다. 모바일 측에서 Unity의 기본 설정은 30프레임입니다.

Application.targetFrameRate를 통해 런타임 시 프레임 속도를 동적으로 조정할 수 있습니다. 예를 들어 특정 느리거나 정적 장면에서는 프레임 수를 30개 미만으로 제한할 수도 있습니다. 그런 다음 플레이어가 수행하는 동안 프레임 속도를 높이십시오.

지나치게 복잡한 계층 구조 방지

계층구조를 단순화하세요! GameObject에 중첩 수준이 필요하지 않은 경우 중첩 관계를 최대한 단순화하십시오. 더 작은 계층은 멀티스레딩을 통해 장면 변환을 새로 고치는 데 도움이 됩니다 . 복잡한 계층 구조는 더 많은 계층적 변환을 가져오는 동시에 불필요한 계산과 더 많은 가비지 수집을 생성합니다.

변환에 대한 더 나은 이해와 연결을 얻으려면 계층 구조 최적화 및 통합 대화를 참조할 수 있습니다 .

두 번 이 아닌 번만 변신하세요

마찬가지로 Transform을 이동할 때 Transform.SetPositionAndRotation을 사용하여 객체의 위치와 회전을 동시에 새로 고칠 수 있습니다. 이렇게 하면 변환을 두 번 새로 고쳐서 발생하는 불필요한 오버헤드를 피할 수 있습니다.

런타임에 GameObject를 인스턴스화해야 하는 경우 간단하고 효과적인 최적화 방법은 인스턴스화 중에 부모 객체와 위치 및 회전 정보를 직접 설정하는 것입니다.

GameObject 인스턴스화(프리팹, 상위);

GameObject Instantiate(prefab, 상위, 위치, 회전);

객체 인스턴스화에 대해 자세히 알아보려면 스크립팅 API를 참조하세요 .

수직동기화(Vsync)가 켜져 있는 경우

모바일 장치는 절반 프레임 렌더링을 지원하지 않습니다. 에디터에서 수직 동기화를 비활성화하더라도( 프로젝트 설정 > 품질 ), 하드웨어 수준에서는 수직 동기화가 계속 활성화됩니다. CPU가 충분히 빠르게 새로 고침되지 않으면 현재 프레임이 유지되어 효과적으로 fps가 줄어듭니다 .


자산 _

리소스 관리 작업(자산 파이프라인)은 애플리케이션 성능에 큰 영향을 미칠 수 있습니다. 숙련된 기술 아티스트는 팀이 자산 형식, 매개변수 및 가져오기 설정을 정의하고 요구하는 데 도움을 줄 수 있습니다.

기본 설정에 의존하지 마십시오. 그에 따라 텍스처 및 기하학적 메시와 같은 리소스를 최적화하려면 다양한 플랫폼 재작성 태그를 사용하십시오. 설정이 잘못되면 패키징 크기가 커지고 패키징 시간이 길어지며 메모리 사용량이 늘어납니다. 최적의 설정을 보장하기 위해 특정 프로젝트에 대한 기본 설정을 사용자 정의하는 데 도움이 되는 사전 설정 기능을 사용해 보십시오 .

미술 자원 관리를 보다 효과적으로 수행하려면 이 문서를 참조할 수 있습니다.

https://docs.unity3d.com/Manual/ImportingAssets.html

또는 Unity Learn 웹사이트에서 " 모바일 애플리케이션을 위한 3D 아트 최적화 " 를 알아보세요.

텍스처를 올바르게 가져오기

텍스처 리소스는 많은 메모리 공간을 차지할 가능성이 높으므로 텍스처 가져오기 설정에 주의를 기울일 가치가 있습니다. 일반적으로 다음 제안 사항을 참조할 수 있습니다.

더 작은 최대 크기 : 효과가 허용되는 경우 가장 낮은 설정을 사용합니다. 이렇게 하면 손실 없이 매우 효율적인 방식으로 텍스처 메모리를 줄일 수 있습니다. 

2의 거듭제곱 ( POT ) 사용: Unity에서는 모바일 텍스처 크기가 2의 거듭제곱(POT) 압축 형식(PVRCT 또는 ETC)이어야 합니다.

아틀라스 사용 : 여러 텍스처를 하나의 텍스처로 결합하면 그리기 호출을 줄이고 렌더링 효율성을 높일 수 있습니다. Unity SpriteAtlas 또는 타사 플러그인 Texture Packer를 사용하여아틀라스를 패키징할 수 있습니다.

읽기/쓰기 비활성화 옵션 : 활성화되면 이 옵션은 텍스처차지하는 메모리 크기를 두 배로 늘립니다. GPU 주소 지정 가능 메모리로텍스처생성하여모두GPUCPU 대부분의 경우 이 옵션을 비활성화합니다. 런타임에 텍스처를 생성해야 하는 경우 Texture2D .Apply 메서드 통해 생성을 강제 한 다음 makeNoLongerReadable 매개변수를 true.

불필요한 Mip 맵 비활성화 : MipMap이 필요하지 않은 2D 스프라이트 및 UI 그래픽과 같은 일부 텍스처는 화면에서 크기를 절대 변경하지 않습니다(3D 개체의 텍스처에서 이 옵션을 활성화하면 카메라 위치가 변경되고 표시 효과가 은 다르다).

올바른 가져오기 설정은 번들 크기를 최적화하는 데 도움이 됩니다.

압축된 질감

아래 예에서는 두 모델이 동일한 텍스처를 사용합니다. 다만 왼쪽의 텍스처 설정의 메모리 사용량은 오른쪽의 8배에 가깝지만 디스플레이 효과에는 큰 차이가 없습니다.

압축되지 않은 텍스처는 더 많은 메모리를 차지합니다.

iOS 및 Android에서 ATSC(Adaptive Scalable Texture Compression)를 사용합니다. 개발 중인 대부분의 게임은 ATSC 압축을 지원하는 최소 사양 장치를 대상으로 합니다(개발 중인 대부분의 게임은 ATSC 압축을 지원하는 최소 사양 장치를 대상으로 함).

다음과 같은 특별한 상황:

프로세서 A7 이하(예: iPhone5, 5S 등)가 탑재된 iOS 장치는 PCVRTC 형식을 사용합니다.

2016년 이전의 Android 기기는 ETC2((Ericsson Texture Compression) 형식을 사용합니다.

PVRTC 또는 ETC 압축 품질이 충분히 높지 않거나 플랫폼 장치가 ASTC 형식을 지원하지 않는 경우 16비트 대신 32비트 텍스처를 사용해 볼 수 있습니다.

다양한 플랫폼의 텍스처 압축 형식에 대한 자세한 내용은 다음 문서를 참조하세요.

Unity - 매뉴얼: 플랫폼별 권장, 기본 및 지원되는 텍스처 형식

메시 가져오기 설정 조정

관련 설정을 고려하지 않고 텍스처, 메쉬 등의 리소스를 가져오면 메모리 사용량이 많이 증가하게 됩니다. 그리드 리소스로 인해 발생하는 메모리 공간을 최소화합니다.

압축된 그리드 : 그리드를 적극적으로 압축하면 하드 디스크 공간 사용량을 줄일 수 있습니다(그러나 런타임 메모리는 영향을 받지 않습니다). 메시의 압축과 다양한 매개변수는 메시의 최종 효과에 영향을 미치므로, 모델에 적합한 수준을 찾기 위해 다양한 압축 수준을 테스트해야 합니다.

읽기/쓰기 비활성화 : 이 옵션을 켜면 그리드의 복사본 두 개가 메모리에 복사됩니다. 하나는 시스템 메모리에 저장되고 다른 하나는 GPU 메모리에 저장됩니다. 대부분의 경우 이 옵션을 비활성화합니다(이 옵션은 Unity 2019.2 이하에서는 기본적으로 켜져 있습니다).

리그 및 BlendShapes 비활성화 : 골격 애니메이션 및 BlendShapes 애니메이션이 필요하지 않은 경우언제든지 이러한 옵션을 비활성화해 보십시오.

가능한 경우 법선 및 접선 비활성화 : 메시의 재질에 법선 및 접선이 필요하지 않다고 판단되면 이를 비활성화하여 불필요한 오버헤드를 절약하십시오 .

다각형 수를 확인하세요

모델의 정확도가 높을수록 메모리와 GPU 사용량이 늘어납니다. 배경을 렌더링하려면 500,000개의 기하학적 면이 필요합니까 ? (배경 형상에 50만 개의 다각형이 필요합니까?) 선택한 DCC 패키지에서 모델을 줄이는 것을 고려하십시오 . 카메라 관점에서 렌더링할 수 없는 일부 얼굴을 삭제합니다. 고정밀 메시가 아닌 텍스처와 노멀 맵을 사용하여 모델 세부 수준을 표현합니다. 

AssetPostprocessor를 사용하여 가져오기 설정 자동화

AssetPostprocessor를 사용하면 자산을 가져올 때 스크립트를 실행할 수 있습니다. 모델, 텍스처, 오디오 및 기타 리소스를 가져오기 전이나 후에 일부 설정을 사용자 정의할 수 있습니다.

주소 지정 가능 자산 시스템 사용

Addressable Asset System( Addressable Asset System )은 리소스를 관리하는 편리한 방법을 제공합니다. "주소"(address) 또는 별칭(alias)별로 AssetBundle을 로드할 수 있습니다. 이 통합 시스템은 로컬 또는 원격(CDN)에서 리소스를 비동기적으로 로드할 수 있습니다.

코드가 아닌 자산(모델, 텍스처, 프리팹, 오디오 또는 전체 장면)을 AssetBundles 로 패키징하는 경우 다운로드 가능한 콘텐츠(DLC) 로 분리할 수 있습니다 .

그런 다음 Addressable 을 사용하여 모바일 앱의 작은 초기 빌드를 만듭니다 . Cloud Content Delivery를 사용하면 게임 콘텐츠를 클라우드에 호스팅하고 전달할 수 있으며 , 플레이어는 클라우드에서 게임 진행 상황을 실시간으로 얻을 수 있습니다. 그런 다음 Addressables를 사용하여 모바일 애플리케이션을 위한 더 작은 초기 빌드를 생성할 수 있습니다. Cloud Content Delivery를 사용  하면 게임을 진행하는 플레이어에게 게임 콘텐츠를 호스팅하고 전달합니다.)

주소 지정 가능 자산 시스템에서 주소(adress)를 사용하여 리소스 로드 

Addressable Asset System이 리소스를 관리하는 방법을 알아보려면 클릭하세요.


그래픽 및 GPU 최적화

Unity는 각 프레임마다 렌더링해야 하는 객체를 결정한 다음 드로우 콜을 생성합니다. 그리기 호출은 그래픽 그리기 API를 호출하여 그래픽(예: 삼각형)을 그리는 반면, 일괄 처리(일괄 처리)는 실행을 위해 그리기 호출 그룹을 함께 배치하는 것입니다.

프로젝트가 더욱 복잡해짐에 따라 GPU의 워크로드를 최적화하려면 특정 파이프라인이 필요합니다. 유니버설 렌더 파이프라인 ( URP ) 은 현재 싱글 패스 포워드 렌더링 방식을 사용하여 모바일 단말기에 더 높은 그래픽 효과를 제공합니다 ( 지연 렌더링 기술은 향후 버전에서 구현될 수 있음 ). ( 유니버설 렌더 파이프라인(URP)은  현재 싱글 패스 방식을 사용합니다. 모바일 플랫폼에 고품질 그래픽을 제공하는 포워드 렌더러(지연 렌더링은 향후 릴리스에서 사용 가능) 콘솔과 PC의 동일한 물리적 기반 조명 및 재료를 휴대폰이나 태블릿 에 맞게 확장 할 수도 있습니다 .

다음 튜토리얼은 그래픽 효율성을 향상하는 데 도움이 될 수 있습니다

그리기 호출 일괄 처리 

함께 그려질 객체를 일괄 처리하면 그리기 객체가 수행하는 그리기 호출 수를 최소화할 수 있습니다. 이렇게 하면 개체 렌더링 시 CPU 소비가 줄어들어 성능이 향상될 수 있습니다. Unity에서 다음 기술을 사용하여 여러 개체를 병합하여 그리기 호출을 줄입니다.

동적 일괄 처리 : 더 작은 메시의 경우 Unity는 CPU에서 정점을 그룹화하고 변환한 후 한 번에 그릴 수 있습니다. 참고: 로우폴리 메시(정점 속성이 900 미만, 정점 개수가 300 미만)가 충분한 경우에만 이 기능을 사용하십시오. 동적 일괄 처리는 이보다 더 많은 정점을 가진 개체를 병합하지 않으므로 이를 활성화하면 CPU가 매 프레임마다 더 작은 메시를 찾아야 하기 때문에 CPU 시간이 소비됩니다.

정적 일괄 처리 : 일부 정적 개체의 경우 Unity는 동일한 재질을 사용하는 개체를 일괄 처리하여 그리기 호출을 줄일 수 있습니다. 정적 일괄 처리는 동적 일괄 처리보다 효율적이지만 더 많은 메모리 공간을 사용합니다.

GPU 인스턴싱 : 동일한 개체가 많은 경우 이 기술은 그래픽 하드웨어를 .

SRP 배치 처리: 유니버설 렌더 파이프라인 에셋 아래 고급 메뉴에서 SRP 배치 처리를 켭니다. 이 옵션은장면에 따라 CPU의 렌더링 시간을 단축 할 수 있습니다. 

이러한 일괄 처리 기술을 활용하여 GameObject를 조정하세요. 

프레임 디버거 사용

프레임 디버거는 각 프레임이 다양한 그리기 호출로 구성되는 방식을 보여줍니다 . 이는 셰이더 속성을 모니터링하고 게임이 렌더링되는 방식을 분석하는 데 도움이 되는 매우 유용한 도구입니다.

다음 문서를 통해 프레임 디버거의 새로운 기능에 대해 알아볼 수 있습니다.

프레임 디버거 작업 - Unity Learn

동적 조명을 너무 많이 사용하지 마십시오.

기존 포워드 렌더러와 비교하여 URP(유니버설 렌더링 파이프라인)는 드로우 콜 수를 크게 줄입니다. 모바일 앱에 동적 조명을 너무 많이 추가하지 마세요. 동적 메시에서 사용자 정의 셰이더 효과나 라이트 프로브를 사용하거나 정적 메시에서 조명을 베이킹하는 것을 고려해 보세요.

이 비교표를 사용하여 URP(유니버설 렌더링 파이프라인)와 내장 렌더링 파이프라인(내장 렌더 파이프라인)의 실시간 조명 간의 차이점을 확인할 수 있습니다.

기능 비교표 | 유니버설RP | 10.4.0


프레임 디버거는 각 프레임을 별도의 단계로 나눕니다.

그림자 비활성화

MeshRenderer 및 조명에서는 그림자 투사가 비활성화됩니다. 따라서 가능할 때마다 섀도우를 비활성화하여 그리기 호출 수를 줄이십시오.

그림자를 가짜로 만들기 위해 캐릭터 아래에 블러 텍스처가 있는 간단한 메쉬나 쿼드를 배치할 수 있습니다. 또는 사용자 정의 셰이더를 사용하여 그림자를 만듭니다.

그리기 호출을 줄이기 위해 그림자 투사를 비활성화합니다.

라이트맵에 조명 굽기

전역 조명(GI)을 사용하여 정적 형상에 멋진 조명을 추가하세요. Contribute GI 속성을 사용하여 객체를 표시하면 고품질 조명 정보를 라이트맵 형식으로 저장할 수 있습니다.

런타임에 구운 그림자와 조명을 렌더링할 때 성능에 영향을 미치지 않습니다. 더 나은 CPU와 GPU는 전역 조명 베이킹 속도를 높일 수 있습니다.

Contribute GI 켜기

라이트매핑 설정(Windows > 렌더링 > 조명 설정) 및 라이트맵 크기를 조정하여 메모리 사용량 제한

이 가이드 와 조명 최적화 에 대한 기사를 참조하면 Unity에서 라이트매핑을 시작하는 데 도움이 됩니다.

조명 레이어 사용

여러 개의 복잡한 조명을 사용하는 장면의 경우 다양한 레벨을 사용하여 모든 객체를 구별한 다음 컬링 마스크 기능을 사용하여 다양한 조명의 영향을 다양한 범위로 제한할 수 있습니다.

레이어 기능은 다양한 조명의 영향을 다양한 범위로 제한할 수 있습니다.

움직이는 물체에 라이트 프로브 사용

라이트 프로브는 장면의 빈 공간에 대해 구운 조명 정보를 저장하고 고품질 조명 효과(직접 및 간접)를 제공합니다. 그들은 동적 조명보다 계산 속도가 훨씬 빠른 구형 조화(Spherical Harmonics)를 사용했습니다.

라이트 프로브는 배경의 동적 개체를 조명합니다.

세부 수준 ( LOD ) 사용

객체가 움직일 때 LOD 기능은 객체를 더 간단한 메시로 전환하고 더 간단한 재료와 셰이더를 사용하여 GPU 성능을 향상시키는 데 도움이 됩니다.

Unity 학습 웹사이트에서 Working with LOD 과정을 수강하여 자세한 내용을 알아보세요 .

LOD 그룹을 사용하는 메시 인스턴스 

 

서로 다른 해상도에서 동일한 모델의 메쉬 정점 차이

Occlusion Culling을 사용하여 숨겨진 개체 제거

다른 개체 뒤에 숨겨진 일부 개체는 여전히 렌더링되어 리소스를 소비할 수 있습니다. 폐색 컬링을 사용하여 폐기합니다.

카메라 시야 외부의 절두체 선별은 자동화되었으며, 폐색 선별은 기본 프로세스입니다. 개체를 Static Occluders 또는 Occludees 로 설정 하고 Window > Rendering > Occlusion Culling 대화 상자를 통해 베이킹하면 됩니다 . 이것이 모든 시나리오에 적합하지는 않지만 컬링을 사용하면 대부분의 경우 성능이 향상될 수 있습니다.

자세한 내용을 보려면 Occlusion Culling 작업 튜토리얼을 클릭하세요 .

기본 모바일 해상도에 주의하세요

휴대폰과 태블릿은 점점 더 발전하고 해상도도 점점 높아지고 있습니다.

일부 성능을 향상시키기 위해 출력 해상도를 낮추려면 Screen .SetResolution (width, height, false)을 사용하십시오 . 게임 그래픽과 성능의 균형을 맞추기 위해 여러 해상도를 구성합니다.

카메라 수 제한

모든 카메라는 의미 있는 작업을 수행하는지 여부에 관계없이 어느 정도 성능 오버헤드를 발생시킵니다. 렌더링에 필요한 카메라 구성요소만 사용하십시오. 일부 저가형 장치에서는 각 카메라의 CPU 시간이 최대 1ms까지 걸릴 수 있습니다.

복잡한 셰이더 ( shader ) 를 피하십시오.

유니버설 렌더링 파이프라인(URP)은 이미 일부 자체 발광 셰이더와 조명 없는 셰이더를 제공하며 모바일 플랫폼에 최적화되어 있습니다. 런타임 메모리 사용량에 큰 영향을 미칠 수 있으므로 셰이더 변경을 최소화하세요. 범용 렌더링 파이프라인에서 제공하는 셰이더가 요구 사항을 충족할 수 없는 경우 셰이더 그래프를 사용하여 셰이더를 사용자 정의할 수 있습니다. 셰이더 그래프를 사용하여 셰이더를 시각적으로 생성하는 방법을 보려면 여기를 클릭하세요 .

셰이더 그래프를 사용하여 맞춤형 셰이더 만들기

오버드로 알파 블렌딩 줄이기

불필요한 투명 또는 반투명 이미지를 그리지 마십시오. 오버드로 및 알파 블렌딩은 모바일 플랫폼의 성능에 심각한 영향을 미칩니다(모바일 플랫폼은 결과적인 오버드로 및 알파 블렌딩으로 인해 큰 영향을 받습니다). 거의 투명한 이미지나 효과를 겹치지 마십시오. RenderDoc 그래픽 디버거를 사용하여 오버드로를 검사 할 수 있습니다 .

화면 후처리 사용 줄이기

전체 화면 화면 후처리 효과로 인해 게임 성능이 크게 저하됩니다. 예술적 효과를 개발할 때 화면 후처리 효과를 주의해서 사용하십시오.

모바일 앱에서 간단한 후처리 효과 사용

Renderer .material 을 주의해서 사용하세요.

스크립트에서 Renderer.material을 사용하면 새 재질이 복사되어 반환 됩니다 . 이는 셰이더를 포함하여 일괄 처리된 콘텐츠에 영향을 미칩니다. 배치 객체 의 재질 에 액세스 하려면 Renderer.material 대신 Renderer.sharedMaterial을 사용하세요 .

SkinnedMeshRenderers 최적화

스킨 메쉬를 렌더링하는 것은 성능 집약적입니다. SkinnedMeshRenderer를 사용하는 모든 개체에 실제로 필요한지 확인하세요 . 게임 오브젝트에 특정 시간에만 애니메이션이 필요한 경우 BakeMesh 기능을 사용하여 정적 작업에서 스킨 처리된 메시를 고정한 다음 런타임에 더 간단한 MeshRenderer 로 전환할 수 있습니다 . (게임 오브젝트에 일정 시간 애니메이션만 필요한 경우 BakeMesh를 사용하세요. 정적 포즈에서 스키닝된 메시를 고정하고 런타임 시 더 간단한 MeshRenderer로 교체하는 기능입니다 .

반사 프로브 사용 줄이기

반사 프로브는 사실적인 반사 효과를 생성할 수 있지만 비용이 매우 많이 들 수 있습니다. 저해상도 큐브맵, 컬링 마스크, 텍스처 압축을 사용하여 런타임 효율성을 향상시킬 수 있습니다. 


사용자 인터페이스

UnityUI (UGUI)도 성능 문제의 원인이 되는 경우가 많습니다. Canvas 구성 요소의 UI 요소는 그리드를 생성 및 업데이트하고 GPU에 그리기 호출 명령을 보냅니다. 이 프로세스는 성능을 소모하는 경우가 많으므로 UGUI 사용 시 다음 사항에 주의하시기 바랍니다.

캔버스를 간소화하세요

수천 개의 요소가 포함된 거대한 캔버스가 있는 경우 개별 UI 요소를 업데이트하면 전체 캔버스가 업데이트되어 CPU 스파이크가 발생할 수 있습니다.

여러 캔버스를 지원하는 Unity의 기능을 활용할 수 있습니다. 그런 다음 새로 고침 빈도의 차이에 따라 UI 요소를 분류합니다. 정적 UI 요소를 캔버스 아래에 배치하고 더 작은 하위 캔버스(하위 캔버스)를 만들어 동적 UI 요소를 저장합니다.

각 캔버스의 모든 UI 요소가 동일한 Z 값, 셰이더 및 텍스처 맵을 사용하는지 확인하세요.

보이지 않는 UI 요소 숨기기

게임에는 가끔씩만 나타나는 일부 UI 요소(예: 플레이어가 부상을 입었을 때 한 번만 나타나는 체력 표시줄)가 있을 수 있습니다. 이러한 보이지 않는 UI 요소가 여전히 활성화되어 있으면 그리기 호출이 계속 생성됩니다. 따라서 보이지 않는 모든 UI 요소가 다시 표시될 때까지 직접 비활성화한 다음 다시 활성화합니다.

Canvas를 숨겨야 하는 경우 전체 GameObject를 비활성화하는 대신 Canvas 구성 요소를 비활성화하십시오. 이렇게 하면 메쉬와 정점을 다시 그리는 것을 방지할 수 있습니다.

GraphicRaycasters 사용을 줄이고 Raycast Target을 비활성화합니다.

화면의 터치 및 클릭과 같은 입력 이벤트를 감지하려면 GraphicRaycaster 구성 요소가 필요합니다. 이는 화면의 모든 입력 지점을 감지하여 UI의 RectTransform에 있는지 여부를 감지함으로써 수행됩니다.

계층 패널에서 Canvas의 기본 GraphicRaycaster 구성 요소를 제거합니다. 그런 다음 상호 작용이 필요한 요소(예: 버튼, 스크롤 사각형 등)에 별도로 GraphicRaycaster 구성 요소를 추가합니다.

기본적으로 활성화되어 있는 반전된 그래픽 무시 옵션을 비활성화합니다.

마찬가지로 Raycast Target이 필요하지 않은 모든 텍스트와 이미지에 대해 이 옵션을 비활성화합니다 . 복잡한 요소로 구성된 UI에서는 작은 변화만으로도 불필요한 계산이 발생하게 됩니다.

가능하다면 Raycast Target을 비활성화하십시오.

레이아웃 그룹 구성요소를 주의해서 사용하세요.

레이아웃 그룹 업데이트 효율성은 상대적으로 낮으므로 이 구성요소를 주의해서 사용하세요. 콘텐츠가 동적이지 않으면 완전히 피하고 대신 비례 레이아웃 에 앵커를 사용하세요 . 또는 레이아웃 그룹이 UI 레이아웃 설정을 완료한 후 코드에서 이를 비활성화합니다.

동적 요소를 관리하기 위해 레이아웃 그룹(가로, 세로, 그리드) 구성 요소가 정말로 필요한 경우 성능 향상을 위해 중첩하지 마십시오.

레이아웃 그룹은 특히 중첩되어 사용될 때 성능에 영향을 미칠 수 있습니다.

큰 목록 그리드 보기를 가능한 한 적게 사용하십시오.

지나치게 큰 목록과 그리드 보기는 성능을 매우 많이 소모합니다. 거대한 목록이나 그리드 보기(예: 수백 개의 제품으로 구성된 인벤토리 페이지)를 만들어야 하는 경우 각 제품에 대해 새 UI 요소를 만드는 대신 작은 UI 요소 개체 풀을 재사용할 수 있습니다. 이 예를 참조하면 더 자세히 이해할 수 있습니다.

겹치는 요소를 많이 피하십시오.

많은 수의 UI 요소(예: 카드 게임의 대량 카드 스택)를 과도하게 레이어링하면 오버드로우가 발생합니다. 게임이 실행되는 동안 UI 요소를 더 적은 수의 레이어와 배치로 동적으로 병합하도록 코드를 사용자 정의하세요.

다양한 해상도 종횡비 사용

현재 많은 모바일 장치는 완전히 다른 해상도와 화면 크기를 사용하여 각 장치가 최상의 사용자 경험을 가질 수 있도록 다양한 장치에 대한 대체 버전의 UI를 제공합니다.

장치 시뮬레이터를 사용하여 지원되는 대부분의 장치에서 UI가 어떻게 보이는지 미리 봅니다 . XCodeAndroid Studio 에서 가상 장치를 생성 할 수도 있습니다 .

장치 에뮬레이터를 사용하여 다양한 화면 형식을 미리 봅니다.

전체 화면 UI를 사용할 때 다른 모든 항목을 숨깁니다 .

일시 중지 페이지와 시작 페이지가 장면의 모든 내용을 다루는 경우 장면에서 3D 카메라를 비활성화하여 렌더링하십시오. 마찬가지로 상단 Canvas 뒤에 숨겨진 모든 Canvas 요소를 비활성화합니다.

화면에 전체 화면 UI가 표시되면 이 페이지를 업데이트하는 데 60fps가 필요하지 않으므로 새로 고침 빈도 Application .targetFrameRate 를 줄이는 것이 좋습니다.

캔버스의 렌더링 모드 에서 월드 공간과 카메라 공간을 선택할 때 카메라를 할당하는 것을 잊지 마세요. 

Event Camera 또는 Render Camera 에 값이 할당되지 않은 경우 Unity는 Camera.main을 강제 로 할당하므로 불필요한 성능 비용이 발생합니다.  

허용되는 경우 캔버스의 렌더링 모드에서는 Screen Space–Overlay 사용을 고려할 수 있으며 , 이 모드에서는 별도의 카메라를 지정할 필요가 없습니다. 

공간 렌더링 모드를 사용할 때 해당 카메라가 이벤트 카메라에 할당되어 있는지 확인하세요. 


오디오 _ _ _

오디오 리소스는 일반적으로 성능 병목 현상이 발생하지 않지만 최적화하여 메모리를 절약할 수 있습니다.

가능하면 모노 오디오를 사용하세요.

3D 공간 오디오를 사용하는 경우 오디오를 모노로 설정하거나 Force To Mon 옵션을 활성화하는 것이 가장 좋습니다 . 공간 배치에 사용되는 다중 채널 오디오는 런타임 시 강제로 모노 오디오 소스로 변환되며, 이 과정에서 CPU 및 메모리 사용량이 증가합니다.

가능하면 압축되지 않은 원시 WAV 파일을 리소스로 사용하세요.

일부 압축 형식(예: MP3, Vorbis)을 사용하는 경우 Unity는 패키징 시 압축을 해제합니다(보조 압축). 이 두 가지 프로세스는 만족스럽지 못한 최종 오디오 효과로 이어집니다.

오디오를 압축하여 비트 전송률 줄이기

압축을 통해 오디오 크기 및 메모리 사용량을 줄입니다.

——Vorbis 형식을 사용해 보십시오 (또는 반복되지 않는 일부 오디오의 경우 MP 3 형식을 사용하십시오).

——짧고 자주 사용되는 일부 오디오의 경우 ADPCM 형식(예: 발자국 소리, 사격 소리)을 사용할 수 있습니다 . 이 압축 형식은 압축되지 않은 PCM 보다 재생 중 디코딩 속도가 더 빠릅니다 .

모바일 음향 효과 리소스의 샘플링 속도는 최대 22050hz를 초과할 수 없습니다. 낮은 오디오 설정을 사용해도 일반적으로 최종 오디오 품질에 특별히 영향을 미치지는 않습니다. 그냥 귀로 느껴보세요.

AudioClip의 가져오기 설정에 맞게 최적화

적절한 로드 유형을 선택하세요.

이 설정은 리소스 크기에 따라 다릅니다.

——작은 크기의 오디오(200kb 미만)는 로드 시 압축 해제 를 선택해야 합니다 . 이렇게 하면 오디오가 원본 16비트 PCM 형식 데이터로 압축 해제되어 CPU 및 메모리 사용량이 증가하므로 이 옵션은 짧은 오디오에만 적합합니다.

——중형 오디오(200kb 이상)는 메모리에 압축 을 선택해야 합니다 .

——큰 크기의 오디오(배경 음악)는 스트리밍 으로 설정되어야 합니다 . 그렇지 않으면 전체 리소스가 한 번에 메모리에 로드됩니다.

메모리에서 음소거된 오디오 언로드 (AudioSources)

버튼 기능 구현 시 볼륨을 0으로 직접 조정하지 마세요. 플레이어가 이 옵션을 자주 전환(음소거/음소거 해제)하지 않는 경우 AudioSource 구성 요소를 삭제( Destroy ) 하고 메모리에서 언로드할 수 있습니다 .


애니메이션 _

Unity의 애니메이션 시스템은 매우 발전했습니다. 가능하다면 다음 설정을 사용하여 모바일 애니메이션을 제한하세요.

일반 리그와 인간형 리그 사용

기본적으로 애니메이션 모델을 Unity로 임포트할 때는 Generic Rig로 설정되지만, 캐릭터 애니메이션을 사용할 때는 개발자들이 보통 Humanoid Rig로 설정합니다.

유니버설 애니메이션에 비해 휴머노이드 애니메이션은 사용하지 않더라도 역동성과 애니메이션 방향 전환을 프레임마다 계산해야 하기 때문에 CPU 계산 시간이 30~50% 정도 늘어납니다. Humanoid Rig 애니메이션에서 이러한 속성을 사용하지 않는 경우 애니메이션을 Generic Rig로 설정하도록 선택하십시오.

애니메이션 컨트롤러의 남용 방지 ( Animator )

애니메이터는 주로 인간형 캐릭터를 구동하는 데 사용되지만 단일 값(예: UI 요소의 투명도 채널)의 변경을 제어하는 ​​데에도 사용되는 경우가 많습니다. 특히 UI 요소와 함께 애니메이터를 과도하게 사용합니다 . 가능하면 모바일에서 레거시 애니메이션 구성요소를 사용하세요.

트위닝 애니메이션을 사용하거나 타사 플러그인을 사용하여 간단한 애니메이션 효과(예: DOTween)를 얻을 수 있습니다.

애니메이터는 성능 집약적일 수 있습니다.


물리학 _

Unity에 내장된 물리 시스템(Nvidia PhysX)은 모바일 장치에서 성능 집약적입니다. 다음 팁을 참조하면 일부 프레임을 저장하는 데 도움이 될 수 있습니다.

설정 최적화

PlayerSettings에서 가능한 경우 Prebake Collision Meshes 옵션을 확인하세요.

사전 굽기 충돌 메시 활성화

물리 설정을 지정했는지 확인하세요 (프로젝트 설정 > 물리) . 레이어 충돌 매트릭스를 최대한 단순화하세요 .  

자동 동기화 변환을 비활성화 하고 충돌 콜백 재사용을 활성화합니다 .

성능 향상을 위해 물리 설정 수정 

성능 문제에 대해서는 프로파일러의 물리 모듈을 주의 깊게 살펴보세요.

충돌체 단순화

메시 충돌체는 성능 집약적입니다. 더 복잡한 메시 충돌체를 더 간단한 기본 요소 또는 메시 충돌체로 대체하여 원래 모양에 가깝게 만듭니다 .

원본 또는 간단한 메시 충돌 상자 사용

물리적 방법을 사용하여 강체 이동 (Rigidbody)

MovePosition 또는 AddForce 클래스 메서드를 사용하여 강체를 이동합니다. Transform 구성 요소를 직접 이동하면 실제 세계가 다시 계산되며, 이는 더 복잡한 장면에서 상당히 성능을 소모합니다. Update 대신 FixUpdate 에서 객체를 이동합니다 .

고정 시간 단계 수정

프로젝트 설정의 기본 고정 시간 간격 은 0.02(50Hz)입니다. 목표 프레임 속도에 따라 이 설정을 수정합니다(예: 30fps의 경우 0.03으로 설정).

그렇지 않고 런타임 시 프레임을 삭제하면 Unity가 한 프레임에서 FixUpdate 메서드를 여러 번 호출하여 잠재적으로 물리학이 많은 콘텐츠로 인해 CPU 성능 문제가 발생할 수 있음을 의미합니다.

최대 허용 시간 단계 이 설정은 프레임이 삭제될 때 수행할 수 있는 물리 계산 및 FixUpdate 이벤트 수를 제한합니다. 이 값을 낮추면 성능이 저하됨에 따라 물리 및 애니메이션이 느려지지만 프레임당 미치는 영향은 줄어듭니다.

목표 프레임 속도에 맞게 고정 시간 단계를 수정하고 최대 허용 시간 단계를 낮추어 성능 문제를 줄입니다.

물리 디버거로 시각화

물리 디버그 창( Window > Analysis > Physics Debugger )을 사용하여 충돌 및 불일치 문제를 해결하세요. 이 창은 GameObject가 충돌할 수 있는 객체를 색상으로 구분된 형태로 시각적으로 표시합니다.

물리 디버거는 물리 개체가 상호 작용하고 충돌할 수 있는 개체를 직관적으로 보여줍니다.

관련 정보에 대한 자세한 내용은 Unity 공식 문서인 Physics Debug Visualization을 참조하세요.
 


워크플로 및 협업

Unity에서 프로젝트를 패키징하는 것은 대규모 작업이며 일반적으로 많은 개발자가 참여합니다. 프로젝트 설정이 팀에 최적인지 확인하세요.

버전 제어 사용

모든 사람은 특정 유형의 버전 제어를 사용해야 합니다. 에디터 세팅의 Asset Serialization Mode 가 Force Text 로 설정되어 있는지 확인하세요 . 

타사 버전 제어 도구(예: Git)를 사용하는 경우 버전 제어 설정 의 모드가 Visible Meta Files 로 설정되어 있는지 확인하세요 .   

Unity에는 장면과 프리팹을 병합하기 위한 마크업 언어(YAML, 사람이 읽을 수 있는 직렬화 언어) 도구가 이미 내장되어 있습니다. 관련 정보에 대한 자세한 내용은 Unity의 공식 문서인 Smart Merge를 참조하세요.

버전 관리 도구는 팀 작업에 필수적입니다. 버그를 찾고 문제가 있는 버전을 찾는 데 도움이 될 수 있습니다. 프로젝트 버전 및 릴리스를 관리하기 위해 브랜치 및 태그를 사용하는 등의 올바른 개발 프로세스를 따르십시오.

Plastic SCM은 Unity가 게임 개발을 위해 공식적으로 권장하는 버전 관리 도구입니다.

더 큰 장면 분할

너무 크고 단일 장면은 공동 개발에 도움이 되지 않습니다. 레벨을 더 작은 장면으로 분할하면 아티스트와 디자이너가 개발에 더 쉽게 협력하는 동시에 충돌 가능성도 최소화할 수 있습니다.

런타임 시 SceneManager .LoadSceneAsync 사용 하면 LoadSceneMode .Additive 매개 변수를 추가하여 장면을 로드할 수 있습니다 .

사용하지 않는 리소스 제거

타사 플러그인 및 라이브러리와 함께 번들로 제공되는 일부 사용되지 않는 리소스에 유의하세요. 여기에는 테스트에 사용된 일부 리소스와 스크립트가 포함되어 있으며 수동으로 제거하지 않은 경우 패키지에 포함되었을 수 있습니다. 사용하지 않는 리소스는 처음에 제거해야 합니다.

Unity  Accelerator를 사용하여 공유 속도 향상

Unity Accelerator는 Unity 에디터 콘텐츠를 더 빠르게 공유할 수 있게 해주는 협업( Collaborate ) 서비스 프록시 및 캐시입니다. 팀이 로컬 네트워크에서 작업하는 경우 프로젝트의 일부를 다시 구축할 필요가 없으므로 다운로드 시간이 크게 단축됩니다. Unity Teams Advanced를 사용하면 액셀러레이터가 리소스를 공유할 수도 있습니다.


Unity 성공 사례 ( Unity 통합 성공 ) 

유니티와의 공식적인 협력이 성공한 사례인 것 같습니다.

관심 있는 분들은 다음 주소를 방문하여 자세히 알아보세요.

Unity 통합 성공

문의 양식


결론 _

Unity 블로그Unity 커뮤니티Unity 학습 포럼 에서 #unitytips 태그를 사용하여 추가 최적화 지식, 팁, 뉴스를 얻을 수 있습니다 .

성능 최적화는 광범위한 주제입니다. 모바일 장치 하드웨어의 작동 방식과 성능 제한을 이해하세요. 프로젝트에 가장 적합하고 효과적인 솔루션을 찾으려면 Unity의 공식 클래스, 구성 요소, 알고리즘, 데이터 구조 및 해당 플랫폼의 성능 분석 도구를 이해하고 배워야 합니다.

물론 당신의 창의성도 과소평가될 수 없습니다.

추천

출처blog.csdn.net/qq302756113/article/details/123872531