[Unity] Unity Performance Tuning Bible 훑어보기 (8)

ChangBeom·2024년 8월 6일

[4.5 Particle System]

 게임 이펙트는 게임 연출에 필수적인 요소로, 유니티에서는 Particle System을 많이 사용한다. 이 장에서는 퍼포먼스 튜닝 관점에서 Particle System의 실패하지 않는 사용법과 주의점에 대해 소개한다.

 중요한 것은 다음 두 가지이다.

  • 파티클 개수 줄이기
  • 노이즈가 많으므로 주의

[4.5.1 파티클 개수 줄이기]

 Particle System은 CPU에서 동작하는 파티클이기 때문에 파티클 수가 많을수록 CPU 부하가 높아진다. 기본 방침으로 필요한 최소한의 파티클 수로 설정하는 것이 좋다. 필요에 따라 개수를 조정하자.

 파티클 개수를 제한하는 방법은 두 가지가 있다.

  • Emission 모듈의 방출 개수 제한
  • 메인 모듈의 Max Particles에서 최대 방출 개수 제한

  • Rate over Time : 초당 방출하는 개수
  • Bursts -> Count : 버스트 타이밍에 방출하는 개수

 이 설정들을 조정하여 필요한 최소한의 파티클 수가 되도록 설정하자.

 또 다른 방법은 메인 모듈의 Max Particles이다. 위 예시에서는 1000개 이상의 파티클은 방출되지 않는다.

<Sub Emitters에서 주의할 점>
 파티클 수를 줄이는 데 있어 서브 이미터 모듈도 주의해야 한다.

 Sub Emitters 모듈은 특정 타이밍(생성 시, 수명이 다했을 때 등)에 임의의 Particle System을 생성하는데, Sub Emitters의 설정에 따라서는 한꺼번에 피크 수에 도달할 수 있으므로 사용 시 주의해야 한다.

[4.5.2 노이즈가 심하므로 주의]

노이즈 모듈의 Quality는 부하가 걸리기 쉽다. 노이즈는 유기적인 파티클을 표현할 수 있고, 간편하게 이펙트의 퀄리티를 높일 수 있어 많이 사용된다. 자주 사용하는 기능인 만큼 성능에 신경을 써야 하는 부분이다.

  • Low(1D)

  • Midium(2D)

  • High(3D)

     Quality는 차원이 올라갈수록 부하는 올라간다. 만약 노이즈가 필요하지 않다면 노이즈 모듈을 끄면 된다. 또한 노이즈를 사용해야 한다면 Quality의 설정은 Low를 우선으로 하고, 요구사항에 따라 Quality를 높여가면 된다.

[4.6 Audio]

 사운드 파일을 임포트한 기본 상태는 성능적으로 개선할 점이 있다. 설정 항목은 다음 세가지이다.

  • Load Type
  • Compression Format
  • Force To Mono

 게임 개발에서 자주 사용하는 BGM, 효과음, 보이스에 맞게 설정하자.

[4.6.1 Load Type]

 사운드 파일(Audio Clip)을 로드하는 방법은 3가지가 있다.

  • Decompress On Load
  • Compressed In Memory
  • Streaming

<Decompress On Load>
Decompress On Load는 비압축으로 메모리에 로드한다. CPU 부하가 낮기 때문에 대기 시간이 짧게 재생된다. 반면 메모리 많이 사용한다.
 음계가 짧고 빠르게 재생되는 효과음에 추천한다. BGM이나 음계가 긴 음성 파일에서 사용하면 메모리를 많이 사용하게 되므로 주의가 필요하다.

<Compressed In Memory>
 Compressed In Memory는 AudioClip을 압축된 상태로 메모리에 로드한다. 재생할 때 압축을 풀어서 재생하는 방식이다. 즉, CPU 부하가 높고 재생 지연이 발생하기 쉽다.
 파일 사이즈가 크고, 메모리에 그대로 펼쳐놓고 싶지 않은 사운드나 약간의 재생 지연이 문제가 되지 않는 사운드에 적합하다. 음성으로 사용하는 경우가 많다.

<Streaming>
 Streaming은 이름에서 알 수 있듯이 로드하면서 재생하는 방식이다. 메모리 사용량은 적은 대신 CPU 부하가 높다. 장시간의 배경음악에 사용하는 것을 추천한다.

로딩 방법 및 주요 사용 용도 정리

종류용도
Decompress On Load효과음
Compressed In Memory음성
StreamingBGM

[4.6.2 Compression Format]

 Compression format은 AuioClip 자체의 압축 포맷이다.

<PCM>
비압축이며, 메모리를 많이 소모한다. 음질에 대한 요구가 매우 높은 경우가 아니라면 설정하지 않는 것이 좋다.

<ADPCM>
PCM에 비해 메모리 사용량은 70% 감소하지만 음질은 떨어지며, Vorbis에 비해 CPU부하가 현저히 적은 것이 특징이다. 즉, 전개 속도가 빠르기 때문에 즉각적인 재생이나 대량으로 재생하는 사운드에 적합하다. 구체적으로 발소리, 충돌음, 무기 등 노이즈가 많으면서도 대량으로 재생해야 하는 사운드에 적합하다.

<Vorbis>
비가역 압축 포맷이기 때문에 PCM보다 음질은 떨어지지만, 파일 크기는 작아진다. 유일하게 Quality를 설정할 수 있어 미세 조정이 가능하다. 모든 사운드(BGM, 효과음, 음성)에서 가장 많이 사용되는 압축 형식이다.

압축 방법 및 주요 사용 용도 정리

종류용도
PCM사용하지 않음
ADPCM효과음
VorbisBGM,효과음,음성

[4.6.3 샘플 레이트 지정]

샘플 레이트를 지정하여 품질을 조절할 수 있다. 모든 압축 포맷을 지원한다. Sample Rate Setting에서 3가지 방법을 선택할 수 있다.

<Preserve Sample Rate>
 기본 설정이다. 원본 음원의 샘플 레이트가 채택된다.

<Optimize Sample Rate>
 Unity측에서 분석하여 가장 높은 주파수 성분을 기준으로 자동 최적화한다.

<Override Sample Rate>
 원본 음원의 샘플 레이트를 덮어쓴다. 8000~192,000Hz까지 지정할 수 있다. 원본 음원보다 높게 설정해도 음질은 올라가지 않는다. 원본 음원보다 샘플 레이트를 낮추고 싶을 때 사용한다.

[4.6.4 효과음은 Force To Mono 설정]

Unity는 기본 상태에서 스테레오로 재생되지만, Force To Mono를 활성화하면 모노로 재생된다. 모노 재생을 강제하면 좌우 각각의 데이터를 보유하지 않아도 되므로 파일 크기와 메모리 크기가 절반으로 줄어든다.

 효과음은 모노로 재생해도 문제가 없는 경우가 많다. 또한 3D 사운드도 모노 재생이 더 좋은 경우가 있다. 고려해서 Force To Mono를 활성화하는 것이 좋다. 퍼포먼스 튜닝 효과도 먼지가 쌓이면 산더미처럼 쌓인다. 모노 재생에 문제가 없다면 적극적으로 Force To Mono를 활성화 시키자.

성능 튜닝과는 조금 다른 이야기지만 음성 파일은 무압축으로 유니티로 가져오는 것이 좋다. 압축된 것을 가져오면 Unity 측에서 디코딩 & 재압축을 하기 때문에 품질 저하가 발생한다.

[4.7 Resources / StreamingAssets]

 프로젝트에는 특별한 폴더가 존재한다. 특히 다음 두가지는 성능 측면에서 주의가 필요하다.

  • Resources 폴더
  • StreamingAssets 폴더

 일반적으로 Unity는 씬, 머티리얼, 스크립트 등에서 참조된 오브젝트만 빌드에 포함한다.

<예시> : 스크립트에서 참조된 오브젝트 예시


//	참조된 오브젝트는 빌드에 포함된다.
[SerializeField] GameObject sample;

 앞의 특수 폴더는 규칙이 다르다. 저장한 파일은 빌드에 포함된다. 즉, 실제로 필요하지 않은 파일도 저장되어 있으면 빌드에 포함되어 빌드 크기가 커질 수 있다.
문제는 프로그램에서 확인할 수 없다는 것이다. 블필요한 파일을 육안으로 확인해야하므로 시간이 오래 걸린다. 이러한 폴더에는 주의해서 파일을 추가해야 한다.
 하지만 프로젝트가 진행되면서 저장 파일은 계속 늘어날 수 밖에 없다. 그 중에는 더 이상 사용하지 않는 불필요한 파일이 섞여 있을 수도 있다. 결론적으로 정기적인 저장 파일 검토를 추천한다.

[4.7.1 시작 시간을 느리게 하는 Resources 폴더]

Resources폴더에 많은 양의 오브젝트를 저장하면 앱 실행 시간이 길어진다. Resources 폴더는 문자열 참조로 오브젝트를 로드할 수 있는 구식 편의 기능이다.

<예시> : 스크립트에서 참조된 오브젝트


var object = Resources.Load("aa/bb/cc/obj");

 다음과 같은 코드로 오브젝트를 로드할 수 있다. Resources 폴더에 저장해두면 스크립트에서 오브젝트에 접근할 수 있기 때문에 자주 사용하게 된다. 하지만 Resources 폴더에 너무 많이 넣으면 앞서 언급했듯이 앱 실행 시간이 길어진다. Unity 시작 시 전체 Resources폴더의 구조를 분석하여 조회 테이블을 생성하기 때문이다. 가급적 Resources 폴더의 사용을 최소화하자.

[4.8 Scriptable Object]

 ScriptableObject는 YAML의 에셋으로, 텍스트 형식으로 파일 관리하고 있는 프로젝트가 많을 것이다. 명시적으로 [PreferBinarySerialization] Attribute를 지정하여 저장 형식을 바이너리 형식으로 변경할 수 있다. 주로 데이터 양이 많은 에셋의 경우, 바이너리 형식으로 저장하면 쓰기/읽기 성능이 향상된다.
 하지만 당연히 바이너리 포맷의 경우 병합 툴 등에서 다루기 어려워진다. 에셋 업데이트가 덮어쓰기만 하면 되는 변경 차이를 텍스트로 확인할 필요가 없는 에셋이나, 게임 개발이 완료되어 더 이상 데이터 변경이 이루어지지 않는 에셋을 지정하는 것이 좋다. [PreferBinarySerialization] 적극적으로 사용하자.

Scriptable Object를 사용할 때 흔히 범하기 쉬운 실수는 클래스 이름과 소스 코드의 파일 이름 불일치이다. 클래스와 파일은 반드시 같은 이름을 사용해야 한다. 클래스 생성 시 이름 지정에 주의하면서 .asset 파일이 올바르게 직렬화되어 바이너리 형식으로 저장되어 있는지 확인하자.

<예시> : ScriptableObject 구현


/*
*	소스코드 파일명이 ScripableObjectSample.cs인 경우
*/

//	직렬화 성공
[PreferBinarySerialization]
public sealed class ScripableObjectSample : ScripableObject
{
	...
}

//	직렬화 실패
[PreferBinarySerialization]
public sealed class MyScripableObject : ScripableObject
{
	...
}

0개의 댓글