블로그 이미지
Every unexpected event is a path to learning for you.

카테고리

분류 전체보기 (2729)
Unity3D (813)
Script (91)
Extensions (14)
Effect (3)
NGUI (77)
UGUI (8)
Physics (2)
Shader (36)
Math (1)
Design Pattern (2)
Xml (1)
Tips (200)
Link (22)
World (1)
AssetBundle (25)
Mecanim (2)
Plugins (67)
Trouble Shooting (68)
Encrypt (7)
LightMap (4)
Shadow (4)
Editor (8)
Crash Report (3)
Utility (9)
UnityVS (2)
Facebook SDK (2)
iTween (3)
Font (10)
Ad (14)
Photon (2)
IAP (1)
Google (8)
Android (45)
iOS (41)
Programming (474)
Server (33)
Unreal (4)
Gamebryo (56)
Tip & Tech (227)
협업 (57)
3DS Max (3)
Game (12)
Utility (136)
Etc (96)
Link (32)
Portfolio (19)
Subject (90)
iOS,OSX (51)
Android (14)
Linux (5)
잉여 프로젝트 (2)
게임이야기 (3)
Memories (20)
Interest (38)
Thinking (38)
한글 (30)
PaperCraft (5)
Animation (408)
Wallpaper (2)
재테크 (18)
Exercise (3)
나만의 맛집 (3)
냥이 (10)
육아 (16)
Total
Today
Yesterday
03-19 00:10

For a while I was struggling with high crash rates on Android due to a "signal 11 (SIGSEGV), code 1 (SEGV_MAPERR)" error in /lib/arm64/libunity.so

Unity 2021.3.26f1 (but also in all earlier Unity 2021, 2020 and 2019 versions I tried). URP 12.1.11.

SOLUTION:
The solution was to disable both Multithreaded Rendering and Graphics Jobs (I had both enabled).



Detailed Error log (with symbols):

 
2023.06.16 16:11:05.189 8877 8946 Error CRASH *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
2023.06.16 16:11:05.189 8877 8946 Error CRASH Version '2021.3.26f1 (a16dc32e0ff2)', Build type 'Release', Scripting Backend 'il2cpp', CPU 'arm64-v8a'
2023.06.16 16:11:05.189 8877 8946 Error CRASH Build fingerprint: 'Nokia/Onyx_00WW/B2N_sprout:10/QKQ1.190828.002/00WW_4_15N:user/release-keys'
2023.06.16 16:11:05.189 8877 8946 Error CRASH Revision: '0'
2023.06.16 16:11:05.189 8877 8946 Error CRASH ABI: 'arm64'
2023.06.16 16:11:05.189 8877 8946 Error CRASH Timestamp: 2023-06-16 16:11:05+0200
2023.06.16 16:11:05.189 8877 8946 Error CRASH pid: 8877, tid: 8946, name: Thread-5  >>> com.kamgam.sbr2 <<<
2023.06.16 16:11:05.189 8877 8946 Error CRASH uid: 10398
2023.06.16 16:11:05.189 8877 8946 Error CRASH signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x17
2023.06.16 16:11:05.189 8877 8946 Error CRASH Cause: null pointer dereference
2023.06.16 16:11:05.189 8877 8946 Error CRASH     x0  00000072101ca8c0  x1  0000000000000000  x2  0000000000000858  x3  000000000000e56e
2023.06.16 16:11:05.189 8877 8946 Error CRASH     x4  000000000000005b  x5  00000072530c4ddc  x6  0000000000000000  x7  00000000840088d2
2023.06.16 16:11:05.189 8877 8946 Error CRASH     x8  00000072535d7530  x9  00000000fffffff1  x10 0000000000000000  x11 0000000000000000
2023.06.16 16:11:05.189 8877 8946 Error CRASH     x12 0000000000000000  x13 0000000000000000  x14 0000000000029873  x15 0000000000000001
2023.06.16 16:11:05.189 8877 8946 Error CRASH     x16 000000725351b618  x17 000000733e8c7070  x18 0000007167606000  x19 0000000000000858
2023.06.16 16:11:05.189 8877 8946 Error CRASH     x20 0000000000000000  x21 ffffffffffffffff  x22 00000071d0132308  x23 00000072101e1c70
2023.06.16 16:11:05.189 8877 8946 Error CRASH     x24 00000072101e1cf0  x25 0000000000000000  x26 00000072104b3780  x27 000000715000018c
2023.06.16 16:11:05.189 8877 8946 Error CRASH     x28 000000000000273d  x29 000000716841fc20
2023.06.16 16:11:05.189 8877 8946 Error CRASH     sp  000000716841f8c0  lr  0000007252840538  pc  0000007252840548
2023.06.16 16:11:05.189 8877 8946 Error CRASH
2023.06.16 16:11:05.189 8877 8946 Error CRASH backtrace:
2023.06.16 16:11:05.189 8877 8946 Error CRASH       #00 pc 0000000000b7c548  /data/app/com.kamgam.sbr2-MA6dTM-G3o_UvCLJ-IzJ0g==/lib/arm64/libunity.so (BuildId: 0a19a0525ef8627736f4cb908c7e7b6083772483)
2023.06.16 16:11:05.189 8877 8946 Error CRASH       #01 pc 0000000000b8cd8c  /data/app/com.kamgam.sbr2-MA6dTM-G3o_UvCLJ-IzJ0g==/lib/arm64/libunity.so (BuildId: 0a19a0525ef8627736f4cb908c7e7b6083772483)
2023.06.16 16:11:05.189 8877 8946 Error CRASH       #02 pc 0000000000b8ccfc  /data/app/com.kamgam.sbr2-MA6dTM-G3o_UvCLJ-IzJ0g==/lib/arm64/libunity.so (BuildId: 0a19a0525ef8627736f4cb908c7e7b6083772483)
2023.06.16 16:11:05.189 8877 8946 Error CRASH       #03 pc 0000000000b44abc  /data/app/com.kamgam.sbr2-MA6dTM-G3o_UvCLJ-IzJ0g==/lib/arm64/libunity.so (BuildId: 0a19a0525ef8627736f4cb908c7e7b6083772483)
2023.06.16 16:11:05.189 8877 8946 Error CRASH       #04 pc 0000000000b449a0  /data/app/com.kamgam.sbr2-MA6dTM-G3o_UvCLJ-IzJ0g==/lib/arm64/libunity.so (BuildId: 0a19a0525ef8627736f4cb908c7e7b6083772483)
2023.06.16 16:11:05.189 8877 8946 Error CRASH       #05 pc 0000000000d39570  /data/app/com.kamgam.sbr2-MA6dTM-G3o_UvCLJ-IzJ0g==/lib/arm64/libunity.so (BuildId: 0a19a0525ef8627736f4cb908c7e7b6083772483)
2023.06.16 16:11:05.189 8877 8946 Error CRASH       #06 pc 0000000000d3b9a8  /data/app/com.kamgam.sbr2-MA6dTM-G3o_UvCLJ-IzJ0g==/lib/arm64/libunity.so (BuildId: 0a19a0525ef8627736f4cb908c7e7b6083772483)
2023.06.16 16:11:05.189 8877 8946 Error CRASH       #07 pc 0000000000d32ff0  /data/app/com.kamgam.sbr2-MA6dTM-G3o_UvCLJ-IzJ0g==/lib/arm64/libunity.so (BuildId: 0a19a0525ef8627736f4cb908c7e7b6083772483)
2023.06.16 16:11:05.189 8877 8946 Error CRASH       #08 pc 0000000000513ff0  /data/app/com.kamgam.sbr2-MA6dTM-G3o_UvCLJ-IzJ0g==/lib/arm64/libunity.so (BuildId: 0a19a0525ef8627736f4cb908c7e7b6083772483)
2023.06.16 16:11:05.189 8877 8946 Error CRASH       #09 pc 00000000000e6890  /apex/com.android.runtime/lib64/bionic/libc.so (__pthread_start(void*)+36) (BuildId: cf739dbc84bcc78f7a1500721bfb3758)
2023.06.16 16:11:05.189 8877 8946 Error CRASH       #10 pc 0000000000084b6c  /apex/com.android.runtime/lib64/bionic/libc.so (__start_thread+64) (BuildId: cf739dbc84bcc78f7a1500721bfb3758)
2023.06.16 16:11:05.328 8877 8946 Error CRASH Forwarding signal 11
0001.01.01 00:00:00.000 -1 -1 Info  --------- beginning of crash
2023.06.16 16:11:05.328 8877 8946 Fatal libc Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x17 in tid 8946 (Thread-5), pid 8877 (com.kamgam.sbr2)
 
SYMBOLICATED STACK
 
2023.06.16 16:11:05.189 8877 8946 Error CRASH       #00 pc 0000000000b7c548 (DataBufferGLES::FlushMappedRange(unsigned long, unsigned long) at ??:?)  /data/app/com.kamgam.sbr2-MA6dTM-G3o_UvCLJ-IzJ0g==/lib/arm64/libunity.so (BuildId: 0a19a0525ef8627736f4cb908c7e7b6083772483)
2023.06.16 16:11:05.189 8877 8946 Error CRASH       #01 pc 0000000000b8cd8c (BufferGLES::EndWrite(unsigned long) at ??:?)  /data/app/com.kamgam.sbr2-MA6dTM-G3o_UvCLJ-IzJ0g==/lib/arm64/libunity.so (BuildId: 0a19a0525ef8627736f4cb908c7e7b6083772483)
2023.06.16 16:11:05.189 8877 8946 Error CRASH       #02 pc 0000000000b8ccfc (GfxDeviceGLES::EndBufferWrite(GfxBuffer*, unsigned long) at ??:?)  /data/app/com.kamgam.sbr2-MA6dTM-G3o_UvCLJ-IzJ0g==/lib/arm64/libunity.so (BuildId: 0a19a0525ef8627736f4cb908c7e7b6083772483)
2023.06.16 16:11:05.189 8877 8946 Error CRASH       #03 pc 0000000000b44abc (GeometryJobTasks::PutGeometryJobTask(GfxDevice&, GeometryJobTasks::GeometryJobTask*) at ??:?)  /data/app/com.kamgam.sbr2-MA6dTM-G3o_UvCLJ-IzJ0g==/lib/arm64/libunity.so (BuildId: 0a19a0525ef8627736f4cb908c7e7b6083772483)
2023.06.16 16:11:05.189 8877 8946 Error CRASH       #04 pc 0000000000b449a0 (GeometryJobTasks::EndFrame(GfxDevice&) at ??:?)  /data/app/com.kamgam.sbr2-MA6dTM-G3o_UvCLJ-IzJ0g==/lib/arm64/libunity.so (BuildId: 0a19a0525ef8627736f4cb908c7e7b6083772483)
2023.06.16 16:11:05.189 8877 8946 Error CRASH       #05 pc 0000000000d39570 (GfxDeviceWorker::RunCommand(ThreadedStreamBuffer&) at ??:?)  /data/app/com.kamgam.sbr2-MA6dTM-G3o_UvCLJ-IzJ0g==/lib/arm64/libunity.so (BuildId: 0a19a0525ef8627736f4cb908c7e7b6083772483)
2023.06.16 16:11:05.189 8877 8946 Error CRASH       #06 pc 0000000000d3b9a8 (GfxDeviceWorker::RunExt(ThreadedStreamBuffer&) at ??:?)  /data/app/com.kamgam.sbr2-MA6dTM-G3o_UvCLJ-IzJ0g==/lib/arm64/libunity.so (BuildId: 0a19a0525ef8627736f4cb908c7e7b6083772483)
2023.06.16 16:11:05.189 8877 8946 Error CRASH       #07 pc 0000000000d32ff0 (GfxDeviceWorker::RunGfxDeviceWorker(void*) at ??:?)  /data/app/com.kamgam.sbr2-MA6dTM-G3o_UvCLJ-IzJ0g==/lib/arm64/libunity.so (BuildId: 0a19a0525ef8627736f4cb908c7e7b6083772483)
2023.06.16 16:11:05.189 8877 8946 Error CRASH       #08 pc 0000000000513ff0 (Thread::RunThreadWrapper(void*) at ??:?)  /data/app/com.kamgam.sbr2-MA6dTM-G3o_UvCLJ-IzJ0g==/lib/arm64/libunity.so (BuildId: 0a19a0525ef8627736f4cb908c7e7b6083772483)
2023.06.16 16:11:05.189 8877 8946 Error CRASH       #09 pc 00000000000e6890 (libc.so not found)  /apex/com.android.runtime/lib64/bionic/libc.so (__pthread_start(void*)+36) (BuildId: cf739dbc84bcc78f7a1500721bfb3758)
2023.06.16 16:11:05.189 8877 8946 Error CRASH       #10 pc 0000000000084b6c (libc.so not found)  /apex/com.android.runtime/lib64/bionic/libc.so (__start_thread+64) (BuildId: cf739dbc84bcc78f7a1500721bfb3758)
2023.06.16 16:11:05.328 8877 8946 Error CRASH Forwarding signal 11



This give a bit of context: This is not for a few users. The effect was tested on about 200k installs and I am pretty confident by now that it worked.




Not sure if this is a known problem. May this info help others with similar problems.

 

 

[출처] https://forum.unity.com/threads/reducing-android-crash-rate-due-to-graphics-jobs-and-multithreaded-rendering.1454152/

 

Showcase - Reducing Android Crash rate due to Graphics Jobs and Multithreaded Rendering

For a while I was struggling with high crash rates on Android due to a "signal 11 (SIGSEGV), code 1 (SEGV_MAPERR)" error in /lib/arm64/libunity.so...

forum.unity.com

 

[참조] https://ssscool.tistory.com/387

 

[Unity] 유니티 다른폰은 괜찮은데 LG G6에서 테스트 했을때만 Crash 나는 현상 해결 (V/InputMethodManager:

[Unity] 유니티 다른폰은 괜찮은데 LG G6에서 테스트 했을때만 Crash 나는 현상 해결 (V/InputMethodManager: checkFocus: view=android.view.SurfaceView{291d66e VFE...... .F....I. 0,0-1440,2880} next=android.view.SurfaceView{291d66e VFE..

ssscool.tistory.com

[참조] https://devgod.tistory.com/58

 

Unity Crash by 'UnityGfxDeviceW'

유니티 버전을 2021.3x로 업데이트 이후 그래픽 라이브러리에서 'UnityGfxDeviceW'와 같은 메세지가 포함된 크래시가 반복적으로 발생되었다. 해결 : Multithreaded Rendering 옵션 비활성 Compute Skining 옵션 비

devgod.tistory.com

 

 

 

반응형
Posted by blueasa
, |

[링크] https://rito15.github.io/posts/unity-mobile-optimization/

 

유니티 - 모바일 성능 최적화

프로젝트 설정

rito15.github.io

 

반응형
Posted by blueasa
, |

게임 출시를 앞두고, Android플랫폼의 심각한 발열과 낮은 프레임에 대한 최적화를 수행했다.

여러개의 프로젝트를 런칭하면서 쌓인 노하우 및 새로 공부한 지식으로 유의미한 최적화 성과를 거두었기에 최적화 방법을 공유한다.

 

먼저, 최적화 방법 공유에 앞서 최적화 대상 프로젝트의 스펙은 다음과 같다

-Unity 2021.3.8f로 개발

-URP 프로젝트

-NGUI사용

 

최적화 성과 (갤럭시 s8기준)

FPS :  20~30 -> 50~60

용량 : 400mb -> 300mb

발열 : S22에서 심각한 발열로 인해 30~40fps가 나옴 -> S22와 같은 심각한 발열 기기에서 거의 발열 없이 수십분 이상 구동 가능. 안정적인 60fps유지.

 

이와같은 성능을 유지하기 위해선 여러가지 복합적인 이유들이 있겠지만,

untiy editor의 stats기준으로 batch는 많아도 100~200수준을 잡아주는 것이 좋다

(스크립트 병목과 높은 vertex로 인한 성능 하락은 고려하지 않는다)

 

먼저 최적화에 앞서 본인 프로젝트에 대한 프로파일링을 우선 진행하길 바란다.

필자는 최적화에 Unity Profiler와 Memory Profiler(실험적) 을 사용했다

 

profiler를 통해 스크립트 병목의 원인을 추적하고, 메모리 스냅샷을 사용해 메모리 사용량을 최적화하라

 

그리고 최적화의 대상이 CPU처리인지 GPU처리인지도 파악해야 한다.

 

 

 

NGUI관련 최적화

1. UI Atlas의 depth최적화, panel을 최적화한다. 

ngui에서 가장 기본적인 것으로 동일한 panel을 사용하는 widget들의 depth를 정리하여 최적화 해주어야 한다.

무분별한 panel의 사용으로 동일한 atlas를 사용하는 widget이 쪼개져 중복적인 draw call을 야기하지 않도록 해야한다.

 

ngui에서 A와 B아틀라스 2개를 통해 UI를 구성한다면 흔이 2의 draw call을 예상할 것 이다.

하지만 만약 depth가 A A B A BB이런 식으로 ui를 배치한다면 draw call은 4가 된다

2의 draw call을 얻기 위해선 A A A B B B B와 같이 atlas에 따른 ui depth를 정리해주어야 한다.

 

하나의 atlas로 draw되다가 다른 atals를 만나면 중간에 batching이 끊기게 된다.

 

2. 동일한 atlas를 사용하는 widget은 단일 panel에서 최대한 순서를 정렬하여 처리해준다.

필자의 경우 ui atlas를 back / icon / overay / font 이렇게 4가지로 나누어, 정리했으며 

ui가 아무리 많아도 batch는 최대 4만 유지하도록 해주었다.

draw call의 병합 규칙은 두가지가 있는데, 하나는 material, texture, shader가 모두 같다는 것이고 다른 하나는 widget의 레이어가 같거나 인접해야 한다는 것이다.

 

3. NGUI에서 Transform의 변화, 생성, 삭제가 일어나는 객체를 조심해라

NGUI에서는 Panel에 속한 widget의 Transform이 변화(생성/삭제 포함) 하면 해당 panel에 있는 모든 widget을 다시 rendering한다. 

즉, Panel에 연출을 위한 widget이 tween position, scale등을 한다면 매 lateUpdate에 Panel은 drawcallfill을 다시 호출하는 것이다.

NGUI Widget의 Transform이 정적이지 않거나, 생성/삭제가 자주 일어나는 객체라면 완전히 다른 panel의 하위 객체로 두어 격리해두어야 한다.

즉, NGUI에서는 한 panel에 속한 widget의 상태에 변화가 생기면 해당 panel의 모든 atlas를 다시 렌더링해주게끔 되어있다.

 

3-1. 특히 NGUI의 UI Label을 조심해라

UI Label로 데미지 등을 처리할 경우 데미지 연출을 위해 UI Label이 매프레임 tweening하거나 animation을 재생할 수 있다. 이 경우 UI Label은 엄청난 성능 병목을 일으킨다.

매 프레임 움직이는 UILabel이 속한 panel의 draw fill/fill shadow/draw call fill을 야기시킨다.

특히 UI Label에 쉐도우나, 아웃라인 등이 들어가있다면 매프레임 Transform의 변화에 따라 Label을 다시 렌더링 해주게 된다.

이를 방지하기 위해 데미지 폰트 등은 이미지 폰트를 사용하는 것을 추천한다.

 

4. panel의 static상태 활성화

panel로 구성한 ui에 있는 모든 객체가 정적인 것이 보장된다면, panel의 static옵션을 활성화해주면 좋다.

ngui객체도 기본적으로 mono객체이며, static객체가 아니면 모든 ui객체에서 update/lateUpdate가 호출되기에 성능 병목이 발생한다.

정적인 객체의 경우 3번 방법을 참고하여 동적인 객체만 관리하는 panel등으로 격리해주자

 

 

그 외 Unity공통 최적화

1. GC를 줄이자

BinaryFormatter의 Serialize는 엄청난 양의 GC를 야기하며, 디바이스를 freeze시킨다. 이러한 동작은 매프레임 해주지 말고, 스케쥴러를 만들어 처리해주자

 

BigInteger.Parse(string)과 같은 value copy를 야기하는 처리를 피해주자

 

특정 타이밍에 GC.Collect를 수동으로 호출해주자

 

2. URP Setting의 Post Processing의 fast sRGB/Linear Conversions로 gamma공간을 사용하고 있다면 gpu의 부담을 덜어주자

 

3.  SustainedPerformanceMode를 활성화해 지속가능한 성능 옵션을 켜주어, 발열을 방지하자 (이로 인해 기본적인 fps의 하락이 있을 수 있음)

 

4. GPU의 병목/부하가 생기는 Project Setting의 옵션은 비활성화 하자 (Compute Skinning, Graphics Jobs...등)

 

5. Static Batching과 Dynamic batcing을 적극 활용하자

 

6. Texture compression format : ASTC, normal map encoding : DXT5nm-style

 

7. Screen.SetResoultion을 통해 화면 해상도를 지정해주자 (HD~FHD). 이를 해주지 않을 경우 기기의 해상도에 따라 렌더링되기 때문에 발열과 배터리소모의 원인이된다.

 

8. Target Framerate를 설정해주자 (60fps). 만약 프레임상한이 없다면 상위 기기에선 비정상적으로 높은 fps가 발생할 수 있으며 이는 발열/배터리소모의 원인이 될 수 있다.

 

9. realtime shadow는 최대한 피하고, 눈속임을 통해 그림자를 표시할 수 있는 방법을 찾자

quad를 통해 그림자를 표현하고, 이 quad를 dynamic batcing하는 등이 방법이다.

 

10. 가능한 많은 object pooling을 해주자. 

또한 NGUI객체의 경우 객체를 pool에서 회수/반환할 때 gameObject.SetActive보단 화면에 rendering되지 않는 먼 영역으로 좌표를 이동시켜 주는것이 좋은 선택지일 수 있다.

NGUI객체는 오브젝트가 enable/disable될 때 많은 병목을 일으키는 처리를 수행한다

 

11. 거리에 따른 최적화 방법을 숙지하라

Generate mipmap은 기본적을 texture의 용량을 1.3배 정도 부풀린다.

단 한 화면에 render되는 객체가 많을 경우 이는 한 화면의 메모리 부하를 줄여주므로 적극 활용해야한다.

 

또한 오브젝트에 LOD level을 세팅하면 거리에 따라 3D오브젝트의 렌더링 부하를 줄일 수 있지만 용량이 추가적으로 들어가는 것을 유의해야 한다.

 

Aniso Level을 주의해라. Aniso Level은 오브젝트를 그릴 때 단일 텍스쳐라도 멀어지면 흐리게 해주는 효과이다.

Aniso Level이 높을수록 선명해지겠지만 ,처리비용이 많이 든다.

프로젝트 세팅에서 확인하라 (기본값은 Forced On이다)

 

12. Asset의 Read/Write옵션을 주의하라

이 옵션은 기본적으로 비활성화지만 활성화 시 GPU메모리 뿐만 아니라 메인 메모리에도 복사되므로 소비량이 2배로 증가한다.

꼭 필요한 오브젝트의 경우만 식별하여 사용할 것

 

13. 파티클의 shader/material에 따라 render order를 조정해주어라.

NGUI와 같은 개념으로, 파티클에서 사용되는 shader/material도 render order를 조정해주어 batching되도록 해주자

 

14. Resources.Load를 매니징하자

디바이스로 부터 불러온 자원의 경우 사용 빈도에 따라 GC가 발생하지 않도록 상시 메모리에서 들고있는 등의 방법으로 최적화 해줄 수 있다.

 

15. Debug.Log를 주의해라

런타임 빌드 시 프로젝트 세팅에서 로깅 옵션을 완전히 비활성화 하거나, 스크립트에서 define으로 처리를 격리해주어라.

 

Unity Crash관련 팁

이 항목은 필자가 서비스중인 게임의 크래시 문제를 해결한 경험으로 작성되었기에, 지극히 주관적입니다.

 

1. Android환경에서 Vulkan API는 아직 불안정하다. Vulkan내부에서 native crash를 야기할 수 있다. (필자는 opengles 3을 권장)

 

2. Multithread rendering과 compute skinning도 native crash를 야기할 수 있다. 

 

3. 빈번한 Scene Load는 잦은 크래시를 야기할 수 있다.

맵의 전환 등으로 Scene이 load될 때 전 scene의 unload와 새로운 scene의 load중 스크립트가 unload된 scene의 객체 혹은 아직 preload상태의 scene에 접근할 경우 크래시가 발생한다.

 

추가적으로, unity의 scene 로드 구조는 순간적으로 폭발적인 메모리 사용량을 불러올 수 있다.

A장면에서 B장면으로 넘어갈 때 A장면과 B장면이 동시에 메모리에 올라가있는 순간이 존재하며 이 때 메모리 부족으로 크래시가 발생할 수 있다.

 

A장면에서 B장면으로 넘길 때 빈 장면(C)을 넣어 A장면의 메모리가 모두 해제되고, GC가 Collect되게 한 후 B장면을 로드해주는 방식은 아주 유용하다

 

4. Strip Engine Code옵션은 무조건 끄자

압축된 스크립트 dll을 참조하는 순간 native crash가 발생한다

 

 

[출처] https://gall.dcinside.com/mgallery/board/view/?id=game_dev&no=124306

 

최적화 노하우 공유 - 인디 게임 개발 마이너 갤러리

개인적으로 개발관련해서 메모용으로 사용하는 티스토리 블로그에 작성했다가,꽤 많은 분들에게 도움이 될 것 같아 내용만 똑같이 복붙하여 왔습니다.다들 고생하세요.-----게임 출시를 앞두고,

gall.dcinside.com

 

반응형
Posted by blueasa
, |

[링크]

유니티 오브젝트의 null 비교 시 유의사항 1

 

유니티 오브젝트의 null 비교 시 유의사항

다음글: 유니티 오브젝트의 null 비교 시 유의사항 2

overworks.github.io

 

유니티 오브젝트의 null 비교 시 유의사항 2

 

유니티 오브젝트의 null 비교 시 유의사항 2

이전글: 유니티 오브젝트의 null 비교 시 유의사항

overworks.github.io

 

반응형
Posted by blueasa
, |

[2023-11-17 기준 사용 버전] Unity 2022.3.13f1

----

 

2022.3 LTS 버전이 나오고 2022.3.5까지 나온걸 보고 업데이트를 하고 사용했었는데,

2023-11-17 기준 최신 버전인 2023-11-17까지 빌드하고 테스트 해본 결과 아래와 같은 크리티컬한 크래쉬 이슈가 여전히 있었다.

안그래도 Unity 2021보다 Unity 2022가 무거워서 마음에 안들었는데 너무 크리티컬한 버그를 아직도 안고치고 있으니 갑갑함.

덕분에 스토어 올려진 앱이 크래시 증가로 경고까지 뜨고 있다.

 

  [크래쉬 이슈]

- 엔진 자체 메모리 누수로 인한 메모리 부족으로 느려지거나 크래쉬 남

- 파티클 관련 무한 재귀 관련 버그가 있는 건지 이펙트(파티클)가 터지면 간헐적으로 앱이 멈춤(이건 예상)

 

2022.3의 .3은 LTS라고 불리는 버전인데 2022.3 모든 버전에서 메모리 누수가 여전히 나고 있고,

몇일 전에 올라온 2022.3.13f1도 위 2개의 크래쉬 이슈가 이전보다는 줄었지만 여전히 나고 있다.

(유니티는 LTS의 정의를 잘못 생각하고 있는건 아닌지 의심스럽다.)

 

더이상 2022 버전 버그 수정을 기대하면서 쓰는건 뻘짓이라 판단하고 2022 버전을 완전히 버리기로 생각함.

현재 2023 버전은 LTS가 나오려면 멀었기 때문에 2021.3으로 엔진 메이저 버전을 다운그레이드 하고 앱 업데이트를 완료 했다.

 

테스트 상에서는 2022에 있던 크래쉬 이슈가 2021에선 나오지 않는걸 확인했다.

2021.3 버전을 쓰다가 2023.3으로 바로 넘어가야 될 것 같다.

 

P.s. 오늘 유니티 뉴스 보니 버전 레벨링을 개편한다면서 2023을 Unity 6으로 바꾸고 앞으로 버전으로 다시 돌아간다고 함.

       매년 업데이트 하기 힘들었나벼..그래서 출시하면 안되는 버전인 Unity 2022가 나오게 된건 아닌지 의심스럽다

 

[결론]

Unity 2022는 쓰레기니 쓰지맙시다.

Unity 2021 쓰세요~

 

[2022.3 Memory Leak 참조 링크]

https://forum.unity.com/threads/strange-memory-leak-on-2022-3-x.1460224/

 

Question - Strange Memory leak on 2022.3.x

Hi all, So this is an odd one. My game when run on 2021.3, memory sits around 1.3GB on launch. However, ive had reports since making changes over the...

forum.unity.com

https://forum.unity.com/threads/rthandles-api-introduced-catastrophic-memory-leak-bug-in-2022-3-8.1486035/

 

Bug - RTHandles API introduced catastrophic memory leak bug in 2022.3.8

Hi all, It seems there was a very large memory leak bug introduced in 2022.3.8 (on my PC it went as far as filling 32GB RAM and reserving a 32GB page...

forum.unity.com

 

반응형
Posted by blueasa
, |

[링크] https://learnandcreate.tistory.com/642

 

유니티에서 패키지를 기본값으로 재설정하기(reset pacakges to defaults)

유니티에서 패키지를 기본값으로 재설정하기(reset pacakges to defaults) 패키지를 기본값으로 재설정하면 프로젝트에서 사용자가 설치한 모든 패키지들을 제거하고 기본값으로 초기화합니다. 이 작

learnandcreate.tistory.com

 

반응형
Posted by blueasa
, |

With recent Unity versions (2020, 2021 and 2022) Flutter Android builds will take a lot longer, because it also has to compile the IL2CPP code from Unity.

From the Readme:

  • Android builds takes forever to complete Unity 2022.1.*, remove these lines from unityLibrary/build.gradle filecommandLineArgs.add("--enable-debugger")
    commandLineArgs.add("--profiler-report")
    commandLineArgs.add("--profiler-output-file=" + workingDir + "/build/il2cpp_"+ abi + "_" + configuration + "/il2cpp_conv.traceevents")

Here is some testing to check how to speed things up.

Unity settings

IL2CPP Code Generation

  • Build Settings -> IL2CPP Code Generation: select Faster (smaller) builds instead of Faster runtime.
  • Or C# EditorUserBuildSettings.il2CppCodeGeneration = UnityEditor.Build.Il2CppCodeGeneration.OptimizeSize;

C++ compiler configuration

  • In Player settings -> Other settings -> configuration, select Debug.
  • Or C# PlayerSettings.SetIl2CppCompilerConfiguration(BuildTargetGroup.Android, Il2CppCompilerConfiguration.Debug);

Disable script debugging

Don't bother setting this in the Unity settings, it will be overridden by the build script.
Assets/FlutterUnityIntegration/Editor/build.cs
In the function DoBuildAndroid() remove the line enabling script debugging.
playerOptions.options = BuildOptions.AllowDebugging;
This is the same as removing commandLineArgs.add("--enable-debugger") from the build.gradle file after an export.

Measuring results

When you run a Flutter build, there are multiple IL2CPP stages that report their duration, with 2 sections taking far longer than all others.
We can compare these build durations when using different settings in Unity.

Log of the slow armv7 and arm64 sections

Starting: Z:\fuw20221.1.0+7\2021\example\android\unityLibrary\src\main\Il2CppOutputProject\IL2CPP\build\deploy\bee_backend\win-x64\bee_backend.exe --profile="Z:/fuw20221.1.0+7/2021/example/android/unityLibrary/build/il2cpp_armeabi-v7a_Release/il2cpp_cache/buildstate/backend_profiler1.traceevents" --stdin-canary --dagfile="Z:/fuw20221.1.0+7/2021/example/android/unityLibrary/build/il2cpp_armeabi-v7a_Release/il2cpp_cache/buildstate/bee.dag" --continue-on-failure --dagfilejson="Z:/fuw20221.1.0+7/2021/example/android/unityLibrary/build/il2cpp_armeabi-v7a_Release/il2cpp_cache/buildstate/bee.dag.json" FinalProgram
WorkingDir: Z:/fuw20221.1.0+7/2021/example/android/unityLibrary/build/il2cpp_armeabi-v7a_Release/il2cpp_cache/buildstate
ExitCode: 0 Duration: 2m:04s
Build succeeded with 553 successful nodes and 0 failed ones

Starting: Z:\fuw20221.1.0+7\2021\example\android\unityLibrary\src\main\Il2CppOutputProject\IL2CPP\build\deploy\bee_backend\win-x64\bee_backend.exe --profile="Z:/fuw20221.1.0+7/2021/example/android/unityLibrary/build/il2cpp_arm64-v8a_Release/il2cpp_cache/buildstate/backend_profiler1.traceevents" --stdin-canary --dagfile="Z:/fuw20221.1.0+7/2021/example/android/unityLibrary/build/il2cpp_arm64-v8a_Release/il2cpp_cache/buildstate/bee.dag" --continue-on-failure 
--dagfilejson="Z:/fuw20221.1.0+7/2021/example/android/unityLibrary/build/il2cpp_arm64-v8a_Release/il2cpp_cache/buildstate/bee.dag.json" FinalProgram
WorkingDir: Z:/fuw20221.1.0+7/2021/example/android/unityLibrary/build/il2cpp_arm64-v8a_Release/il2cpp_cache/buildstate
ExitCode: 0 Duration: 2m:03s
Build succeeded with 553 successful nodes and 0 failed ones
 

Results

The exact durations here aren't important, as this will be different of every computer and project setup.
This is after flutter clean and a fresh Unity export. Any subsequent runs will be faster because of caching.

Flutter build apk, with an export from Unity 2021.3.5f1 in android/unityLibrary on Windows 10.

Settingarmv7 durationarm64 duration

example project 2m:04s 2m:03s
1 - Code generation (faster builds) 1m:41s 1m:38s
2 - Compiler configuration (debug) 45s 43s
3 - No script debugging 30s 30s
1 + 2 35s 34s
1 + 2 + 3 23s 25s

Conclusion

My advice is to add this to the build script in DoBuildAndroid() for any test or debug builds, remove it for final release builds.

//Assets/FlutterUnityIntegration/Editor/build.cs
bool isReleaseBuild = false;

#if UNITY_2022_1_OR_NEWER
    PlayerSettings.SetIl2CppCompilerConfiguration(BuildTargetGroup.Android, isReleaseBuild ? Il2CppCompilerConfiguration.Release : Il2CppCompilerConfiguration.Debug);
    PlayerSettings.SetIl2CppCodeGeneration(UnityEditor.Build.NamedBuildTarget.Android, UnityEditor.Build.Il2CppCodeGeneration.OptimizeSize);
#elif UNITY_2021_2_OR_NEWER
    PlayerSettings.SetIl2CppCompilerConfiguration(BuildTargetGroup.Android, isReleaseBuild ? Il2CppCompilerConfiguration.Release : Il2CppCompilerConfiguration.Debug);
    EditorUserBuildSettings.il2CppCodeGeneration = UnityEditor.Build.Il2CppCodeGeneration.OptimizeSize;
#endif
 

If it doesn't affect your workflow, disable script debugging.

// playerOptions.options = BuildOptions.AllowDebugging;

And if you are developing on an arm64 device anyway, temporarily remove the armv7 build target from the Unity player settings.

 

 

[출처] https://github.com/juicycleff/flutter-unity-view-widget/issues/643

 

[Android] Tips to reduce android build times. · Issue #643 · juicycleff/flutter-unity-view-widget

With recent Unity versions (2020, 2021 and 2022) Flutter Android builds will take a lot longer, because it also has to compile the IL2CPP code from Unity. From the Readme: Android builds takes fore...

github.com

 

반응형
Posted by blueasa
, |

Unity 2021.3.23f1 이후

Unity 2022 이후

 

----

Unity 2021.3.23f1 부터 유니티 에디터가 (Unity 2021.3.23f1 버전부터) *.androidlib를 폴더가 아닌 파일로 보게 변경된 후,

(관련 이슈 : https://issuetracker.unity3d.com/issues/macos-meta-files-are-created-inside-a-bundle-when-its-imported-into-the-project)

*.androidlib나 *.dll 등의 파일을 Import 하거나 git 등에서 pull 받고 유니티를 재실행하면 제목과 같이 Rever Factory Settings 설정 팝업등이 뜨면서 무한 루프에 빠진다.

 

이를 해결하기 위해서는 Library 폴더를 삭제 후 유니티를 켜서 Library를 새로 생성하게 하면 되는데

전체를 다시 생성하려면 시간이 너무 오래걸린다.

 

확인해보니 아래 파일 2개만 삭제하면 된다고 한다.

에디터 종료 후, 아래 파일 2개를 삭제하고 에디터를 다시 실행해보자.

 

[Library에서 삭제할 파일]

- ./Library/SourceAssetDB

- ./Library/SourceAssetDB-lock

 

 

 

 

반응형
Posted by blueasa
, |

성능이 한정된 기기에서 실행되는 애플리케이션의 충돌을 방지하려면 메모리 최적화가 반드시 필요합니다. 여러 기기를 대상으로 출시하려는 경우, 각 플랫폼에서 최고의 성능을 끌어내기 위해 메모리 사용량을 조정해야 할 수도 있습니다.

 
메모리에 영향을 끼치는 요소는 매우 다양하지만, 그 중에서도 에셋을 중심으로 메모리를 효율적으로 관리할 수 있도록 지원하는 Unity 툴과 최적화할 수 있는 방안에 대해 소개합니다.

 
제공: 오지현 에반젤리스트, 2023년 2월

빌트인 프로파일러 모듈로, 애플리케이션이 메모리를 사용하는 위치에 대한 기본 정보를 제공합니다.
 
메모리 프로파일러 모듈은 애플리케이션에 할당된 전체 메모리를 나타내는 카운터를 시각화합니다. 메모리 모듈을 사용하여 로드된 오브젝트의 수와 카테고리 별로 해당 오브젝트가 차지하는 메모리 양과 같은 정보를 볼 수 있습니다.

2. Memory Profiler 1.0 (필수)
 

Unity 애플리케이션 및 Unity 에디터의 메모리 사용량을 검사하는 데 사용할 수 있는 도구로, 어떤 에셋이 메모리를 사용하고 있는지 애플리케이션의 메모리 할당에 대한 정보를 자세하게 확인할 수 있습니다. 특히 Unity 에디터에 메모리 프로파일러 창을 추가하여 메모리 스냅샷을 캡처, 검사 및 비교할 수 있습니다.

Unity 패키지 관리자를 통해 다운로드하고 메모리를 최적화할 수 있습니다.

▶ Memory Profiler 1.0.0 관련 블로그 아티클 보기


3. Unity Addressables
 

Unity Addressables는 복잡한 라이브 콘텐츠를 전달해야 하는 대규모 제작팀의 요구사항을 보다 효과적으로 지원하기 위한 Unity 에디터 및 런타임 에셋 관리 시스템입니다.
 
Unity Addressables을 활용해 불필요한 에셋의 로드를 방지하는 약한 참조를 도입하여 런타임 메모리를 개선할 수 있습니다.

 

 어드레서블 에셋 시스템으로 메모리 최적화하기 블로그 아티클 보기


4. Audio / Sound 설정
[Force to Mono]
오디오의 스테레오 정보를 없애고 Mono로 만드는 만큼 용량이 줄어듭니다. 특히 모바일에서는 스테레오로 설정할 일이 드물어 추천 드립니다.
 
[읽기 방식(Load type)]
사운드가 어떤 성격인지에 따라 로드 타입과 포맷을 설정하는 것을 추천 드립니다.




[권장 압축 형식(Compression Format)]
● Unity는 하드웨어 가속이 아닌 소프트웨어로 오디오 디코딩을 처리하고 있어 안드로이드/iOS 구분 없이 사용할 수 있는 Vorbis 타입을 권장합니다.
● 매우 짧은 클립의 경우 ADPCM 포맷을 권장 드립니다.
 
※ 오디오는 음소거(Mute) 상태여도 메모리에는 존재하고 있어 선택 옵션이 아니라면, 지우는 것을 권장합니다.

5. Mesh

Mesh 데이터 관리를 통해 메모리를 최적화할 수 있습니다.



Read / Write Enabled 옵션은 CPU와 GPU메모리 양측에 존재하여 옵션을 OFF하는 것이 좋습니다.




6. 셰이더 배리언트
하나의 셰이더라도 여러 조건에 따라 수많은 바이너리로 파생되어 빌드 시간, 패키지 사이즈는 물론 메모리까지 영향을 줄 수 있습니다.
 
셰이더 배리언트의 개념부터 이슈 발생 원인, 최적화하는 방법으로 메모리를 최적화해 보세요.



7. TextMesh Pro
시각적 품질을 크게 개선할 뿐만 아니라 텍스트 스타일 지정 및 텍스처링 부문에서 사용자에게 뛰어난 유연성을 선사하는 TextMesh Pro
 
특히 한글은 초성+중성+종성 조합 방식으로 11,000자가 넘는 글자를 텍스트 아틀라스와 텍스처로 제작한다면 메모리가 커질 수 밖에 없습니다. 메모리 최적화를 위해 사용 시 여러 테스트를 통해 제작하는 것을 권장합니다.


8. 메모리에 영향을 주는 텍스처

대부분의 게임에서는 텍스처로 인한 메모리 이슈가 발생합니다.
 
[Baked Lighting]
Lightmap, Light Probe, Reflection Probe와 같은 조명 설정으로도 메모리 문제가 발생할 수 있습니다. 메모리에 영향을 주는 요소로 적절하게 사용하는 것이 좋습니다.
 
● Lightmap은 배경, 건물과 같은 스태틱 오브젝트에 라이트 결과를 미리 적용하여 저장하기 때문에 텍스처 메모리 이슈가 발생할 수 있습니다.
● Reflection Probe는 6면의 큐브로 만들어진 텍스처로, 텍스처 6개가 생성됩니다. 그에 따라 메모리 이슈 발생 가능성이 큽니다.
 
가능한 시각 효과 대비 사이즈를 작게 제작하고, 적절한 압축 형식을 사용하는 것을 권장합니다.

[텍스처 압축]
 

텍스처 에셋의 화질이 높을수록 픽셀당 비트가 더 높으며, 그에 따라 빌드 크기, 로드 시간, 런타임 메모리 사용량이 늘어납니다.

기기에서 지원하지 않는 포맷 사용 시 압축이 풀리기 때문에 기기별 지원하는 텍스처 포맷을 사용하는 것이 좋습니다. 모바일에서는 ASTC 형식을 사용하는 것을 권장합니다. (타겟 디바이스에 따라 상이)



[Mipmap]

Mipmap(밉맵)은 3D 그래픽스에서 텍스처를 적용하는 과정에서 렌더링 속도를 가속화하기 위해 축소한 비트맵 이미지의 집합으로, 카메라로부터의 거리에 따라 달라질 수 있습니다.


Mipmap 사용 시 원래 텍스처보다 33.3333%의 메모리가 증가합니다. 2D 맵에서는 원근법이 필요하지 않기 때문에 Off를 하는 것이 좋습니다.

[Scene Loading]
Scene 전환 시 기존 Scene A 의 데이터가 남아있는 상황에서 추가적으로 Scene B의 데이터를 로드할 경우 순간적으로 메모리에 과부하가 발생할 수 있습니다.



9. 메모리 최적화에 도움이 되는 Unity 가이드

 

[출처]

https://unitysquare.co.kr/growwith/unityblog/webinarView?id=348&utm_source=facebook-page&utm_medium=social&utm_campaign=korea_unitytipsblog-memory

 

Unity Square

성능이 한정된 기기에서 실행되는 애플리케이션의 충돌을 방지하려면 메모리 최적화가 반드시

unitysquare.co.kr

 

 

반응형
Posted by blueasa
, |

Audio Import 시, 원하는 최적화 관련 설정 자동 셋팅하도록 소스 정리 함.

(AudioCompressionFormat은 심플하게 Vobis / Quality 40으로 통일함.)

 

using System.IO;
using UnityEditor;
using UnityEngine;

public class AssetPostprocessor_Audio : AssetPostprocessor
{
    /*
     * 오디오클립 파일 경로
     * Resources - Sound ┬ BGM - MainBGM
     *                   ├ InGame - SFX
     *                   └ SoundEffect ┬ OutGame
     *                                 ├ UI
     *                                 └ Voice
     * Resources_AssetBundles ┬ sound ┬ sound_effect
     *                        │       ├ sound_main_bgm
     *                        │       ├ sound_sub_bgm
     *                        │       └ sound_voice
     *                        ├ sound_scenario
     *                        └ sound_scenario_StreamingAssets
     */
    void OnPreprocessAudio()
    {
        bool bDefaultSettingChanged = false;
        AudioImporter audioImporter = assetImporter as AudioImporter;
        AudioImporterSampleSettings defaultSampleSettings = audioImporter.defaultSampleSettings;
        AudioImporterSampleSettings iosSampleSettings = audioImporter.GetOverrideSampleSettings("iOS");
        bool biOSSettingChanged = false;

        UnityEditor.SerializedObject serializedObject = new UnityEditor.SerializedObject(audioImporter);
        UnityEditor.SerializedProperty normalize = serializedObject.FindProperty("m_Normalize");

        string strPath = audioImporter.assetPath;
        Debug.LogFormat("[audioImporter.assetPath] {0}", strPath);

        // Folder Name
        if (strPath.StartsWith("Assets/Resources/Sound/BGM"))
        {
            audioImporter.forceToMono = true;
            normalize.boolValue = false;
            audioImporter.loadInBackground = true;
            //audioImporter.ambisonic = false;

            defaultSampleSettings.loadType = AudioClipLoadType.Streaming;
            audioImporter.preloadAudioData = false;
            defaultSampleSettings.compressionFormat = AudioCompressionFormat.Vorbis;
            defaultSampleSettings.quality = 0.4f;   // 40
            defaultSampleSettings.sampleRateSetting = AudioSampleRateSetting.OptimizeSampleRate;

            //iosSampleSettings.loadType = AudioClipLoadType.Streaming;
            //iosSampleSettings.compressionFormat = AudioCompressionFormat.MP3;
            //iosSettingChanged = true;

            bDefaultSettingChanged = true;
        }
        else if (strPath.StartsWith("Assets/Resources/Sound/InGame/SFX"))
        {
            audioImporter.forceToMono = true;
            normalize.boolValue = false;
            audioImporter.loadInBackground = false;
            //audioImporter.ambisonic = false;

            defaultSampleSettings.loadType = AudioClipLoadType.DecompressOnLoad;
            audioImporter.preloadAudioData = true;
            defaultSampleSettings.compressionFormat = AudioCompressionFormat.Vorbis;
            defaultSampleSettings.quality = 0.4f;   // 40
            defaultSampleSettings.sampleRateSetting = AudioSampleRateSetting.OptimizeSampleRate;

            bDefaultSettingChanged = true;
        }
        else if (strPath.StartsWith("Assets/Resources/Sound/SoundEffect/OutGame"))
        {
            audioImporter.forceToMono = true;
            normalize.boolValue = false;
            audioImporter.loadInBackground = false;
            //audioImporter.ambisonic = false;

            defaultSampleSettings.loadType = AudioClipLoadType.DecompressOnLoad;
            audioImporter.preloadAudioData = true;
            defaultSampleSettings.compressionFormat = AudioCompressionFormat.Vorbis;
            defaultSampleSettings.quality = 0.4f;   // 40
            defaultSampleSettings.sampleRateSetting = AudioSampleRateSetting.OptimizeSampleRate;

            bDefaultSettingChanged = true;
        }
        else if (strPath.StartsWith("Assets/Resources/Sound/SoundEffect/UI"))
        {
            audioImporter.forceToMono = true;
            normalize.boolValue = false;
            audioImporter.loadInBackground = false;
            //audioImporter.ambisonic = false;

            defaultSampleSettings.loadType = AudioClipLoadType.DecompressOnLoad;
            audioImporter.preloadAudioData = true;
            defaultSampleSettings.compressionFormat = AudioCompressionFormat.Vorbis;
            defaultSampleSettings.quality = 0.4f;   // 40
            defaultSampleSettings.sampleRateSetting = AudioSampleRateSetting.OptimizeSampleRate;

            bDefaultSettingChanged = true;
        }
        else if (strPath.StartsWith("Assets/Resources/Sound/SoundEffect/Voice"))
        {
            audioImporter.forceToMono = true;
            normalize.boolValue = false;
            audioImporter.loadInBackground = false;
            //audioImporter.ambisonic = false;

            defaultSampleSettings.loadType = AudioClipLoadType.CompressedInMemory;
            audioImporter.preloadAudioData = true;
            defaultSampleSettings.compressionFormat = AudioCompressionFormat.Vorbis;
            defaultSampleSettings.quality = 0.4f;   // 40
            defaultSampleSettings.sampleRateSetting = AudioSampleRateSetting.OptimizeSampleRate;

            bDefaultSettingChanged = true;
        }
        else if (strPath.StartsWith("Assets/Resources_AssetBundles/sound/sound_effect"))
        {
            audioImporter.forceToMono = true;
            normalize.boolValue = false;
            audioImporter.loadInBackground = false;
            //audioImporter.ambisonic = false;

            defaultSampleSettings.loadType = AudioClipLoadType.DecompressOnLoad;
            audioImporter.preloadAudioData = true;
            defaultSampleSettings.compressionFormat = AudioCompressionFormat.Vorbis;
            defaultSampleSettings.quality = 0.4f;   // 40
            defaultSampleSettings.sampleRateSetting = AudioSampleRateSetting.OptimizeSampleRate;

            bDefaultSettingChanged = true;
        }
        else if (strPath.StartsWith("Assets/Resources_AssetBundles/sound/sound_main_bgm"))
        {
            audioImporter.forceToMono = true;
            normalize.boolValue = false;
            audioImporter.loadInBackground = true;
            //audioImporter.ambisonic = false;

            defaultSampleSettings.loadType = AudioClipLoadType.Streaming;
            audioImporter.preloadAudioData = false;
            defaultSampleSettings.compressionFormat = AudioCompressionFormat.Vorbis;
            defaultSampleSettings.quality = 0.4f;   // 40
            defaultSampleSettings.sampleRateSetting = AudioSampleRateSetting.OptimizeSampleRate;

            bDefaultSettingChanged = true;
        }
        else if (strPath.StartsWith("Assets/Resources_AssetBundles/sound/sound_sub_bgm"))
        {
            audioImporter.forceToMono = true;
            normalize.boolValue = false;
            audioImporter.loadInBackground = true;
            //audioImporter.ambisonic = false;

            defaultSampleSettings.loadType = AudioClipLoadType.Streaming;
            audioImporter.preloadAudioData = false;
            defaultSampleSettings.compressionFormat = AudioCompressionFormat.Vorbis;
            defaultSampleSettings.quality = 0.4f;   // 40
            defaultSampleSettings.sampleRateSetting = AudioSampleRateSetting.OptimizeSampleRate;

            bDefaultSettingChanged = true;
        }
        else if (strPath.StartsWith("Assets/Resources_AssetBundles/sound/sound_voice"))
        {
            audioImporter.forceToMono = true;
            normalize.boolValue = false;
            audioImporter.loadInBackground = false;
            //audioImporter.ambisonic = false;

            defaultSampleSettings.loadType = AudioClipLoadType.CompressedInMemory;
            audioImporter.preloadAudioData = true;
            defaultSampleSettings.compressionFormat = AudioCompressionFormat.Vorbis;
            defaultSampleSettings.quality = 0.4f;   // 40
            defaultSampleSettings.sampleRateSetting = AudioSampleRateSetting.OptimizeSampleRate;

            bDefaultSettingChanged = true;
        }
        else if (strPath.StartsWith("Assets/Resources_AssetBundles/sound_scenario"))
        {
            // File Name
            if (strPath.Contains("/bg_"))  // BGM
            {
                audioImporter.forceToMono = true;
                normalize.boolValue = false;
                audioImporter.loadInBackground = true;
                //audioImporter.ambisonic = false;

                defaultSampleSettings.loadType = AudioClipLoadType.Streaming;
                audioImporter.preloadAudioData = false;
                defaultSampleSettings.compressionFormat = AudioCompressionFormat.Vorbis;
                defaultSampleSettings.quality = 0.4f;   // 40
                defaultSampleSettings.sampleRateSetting = AudioSampleRateSetting.OptimizeSampleRate;

                bDefaultSettingChanged = true;
            }
            else if(strPath.Contains("/se_"))  // SFX
            {
                audioImporter.forceToMono = true;
                normalize.boolValue = false;
                audioImporter.loadInBackground = false;
                //audioImporter.ambisonic = false;

                defaultSampleSettings.loadType = AudioClipLoadType.DecompressOnLoad;
                audioImporter.preloadAudioData = true;
                defaultSampleSettings.compressionFormat = AudioCompressionFormat.Vorbis;
                defaultSampleSettings.quality = 0.4f;   // 40
                defaultSampleSettings.sampleRateSetting = AudioSampleRateSetting.OptimizeSampleRate;

                bDefaultSettingChanged = true;
            }
            else    // Etc(SFX?)
            {
                audioImporter.forceToMono = true;
                normalize.boolValue = false;
                audioImporter.loadInBackground = false;
                //audioImporter.ambisonic = false;

                defaultSampleSettings.loadType = AudioClipLoadType.DecompressOnLoad;
                audioImporter.preloadAudioData = true;
                defaultSampleSettings.compressionFormat = AudioCompressionFormat.Vorbis;
                defaultSampleSettings.quality = 0.4f;   // 40
                defaultSampleSettings.sampleRateSetting = AudioSampleRateSetting.OptimizeSampleRate;

                bDefaultSettingChanged = true;
            }
        }
        else if (strPath.StartsWith("Assets/Resources_AssetBundles/sound_scenario_StreamingAssets"))
        {
            // File Name
            if (strPath.Contains("/bg_"))  // BGM(
            {
                audioImporter.forceToMono = true;
                normalize.boolValue = false;
                audioImporter.loadInBackground = true;
                //audioImporter.ambisonic = false;

                defaultSampleSettings.loadType = AudioClipLoadType.Streaming;
                audioImporter.preloadAudioData = false;
                defaultSampleSettings.compressionFormat = AudioCompressionFormat.Vorbis;
                defaultSampleSettings.quality = 0.4f;   // 40
                defaultSampleSettings.sampleRateSetting = AudioSampleRateSetting.OptimizeSampleRate;

                bDefaultSettingChanged = true;
            }
            else if (strPath.Contains("/se_"))  // SFX
            {
                audioImporter.forceToMono = true;
                normalize.boolValue = false;
                audioImporter.loadInBackground = false;
                //audioImporter.ambisonic = false;

                defaultSampleSettings.loadType = AudioClipLoadType.DecompressOnLoad;
                audioImporter.preloadAudioData = true;
                defaultSampleSettings.compressionFormat = AudioCompressionFormat.Vorbis;
                defaultSampleSettings.quality = 0.4f;   // 40
                defaultSampleSettings.sampleRateSetting = AudioSampleRateSetting.OptimizeSampleRate;

                bDefaultSettingChanged = true;
            }
            else    // Etc(SFX?)
            {
                audioImporter.forceToMono = true;
                normalize.boolValue = false;
                audioImporter.loadInBackground = false;
                //audioImporter.ambisonic = false;

                defaultSampleSettings.loadType = AudioClipLoadType.DecompressOnLoad;
                audioImporter.preloadAudioData = true;
                defaultSampleSettings.compressionFormat = AudioCompressionFormat.Vorbis;
                defaultSampleSettings.quality = 0.4f;   // 40
                defaultSampleSettings.sampleRateSetting = AudioSampleRateSetting.OptimizeSampleRate;

                bDefaultSettingChanged = true;
            }
        }

        try
        {
            // 수정됐으면 Save
            if (true == bDefaultSettingChanged)
            {
                audioImporter.defaultSampleSettings = defaultSampleSettings;
                serializedObject.ApplyModifiedProperties();
                if (true == biOSSettingChanged)
                {
                    audioImporter.SetOverrideSampleSettings("iOS", iosSampleSettings);
                }
                audioImporter.SaveAndReimport();

                EditorUtility.SetDirty(audioImporter);

                Debug.LogFormat("[{0}] has been imported to [{1}]\n[Force To Mono] {2}\n[Normalize] {3}\n[Load In Background] {4}\n[Load Type] {5}\n[Compression Format] Default: {6}, iOS: {7}\n[Quality] {8}\n[Sample Rate Setting] {9}",
                                Path.GetFileName(strPath),
                                Path.GetDirectoryName(strPath),
                                audioImporter.forceToMono.ToString(),
                                normalize.boolValue,
                                audioImporter.loadInBackground,
                                defaultSampleSettings.loadType.ToString(),
                                defaultSampleSettings.compressionFormat.ToString(),
                                iosSampleSettings.compressionFormat.ToString(),
                                (defaultSampleSettings.quality * 100f),
                                defaultSampleSettings.sampleRateSetting.ToString()
                                );
            }

            // OnPreprocessAudio() 에서는 Refresh 안함
            //AssetDatabase.Refresh();
        }
        catch (System.Exception e)
        {
            Debug.LogError(e);
        }
    }

    // 파일이 이동한 경우 다시 임포트.
    static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths)
    {
        try
        {
            foreach (string movedAsset in movedAssets)
            {
                if (movedAsset.StartsWith("Assets/Resources/Sound")
                    || movedAsset.StartsWith("Assets/Resources_AssetBundles/sound")
                    || movedAsset.StartsWith("Assets/Resources_AssetBundles/sound_scenario")
                    || movedAsset.StartsWith("Assets/Resources_AssetBundles/sound_scenario_StreamingAssets")
                    )
                {
                    AssetDatabase.ImportAsset(movedAsset);
                }
            }
        }
        catch (System.Exception e)
        {
            Debug.LogError(e);
        }
    }
}

 

[참조]

https://overworks.github.io/unity/2018/09/22/unity-audio-clip-import-guide.html

https://jwidaegi.blogspot.com/2019/07/unity-sound.html?sc=1680659862098#c4452839809969885205

https://www.jianshu.com/p/b389936ff1ad

https://blog.csdn.net/hururu20120502/article/details/121425411

https://drehzr.tistory.com/1016

 

 

반응형
Posted by blueasa
, |