유니티 프로젝트 최적화는 모바일 플랫폼을 중심으로 메모리, CPU, GPU 부하 요인을 다루며, 실제 고객 프로젝트에서 공통적으로 발생하는 문제점과 해결 방안을 공유합니다. 💡
쉐이더 베리언츠는 키워드 추가 시 기하급수적으로 증가하므로, 청크 단위 압축/해제 기능 활성화, 빌드 시 자동 스트리핑 옵션 확인, MultiCompile 지시자를 ShaderFeature로 변경, 그리고 실제 사용 베리언츠를 수집하여 스크립트로 직접 제거하는 것이 중요합니다. 📦
퍼시스턴트 매니저와 시리얼라이즈드 파일의 메모리 점유는 에셋 번들과 밀접하며, 불필요한 번들은 인스턴스 생성 후 AssetBundle.Unload(false)로 언로드하고, 어드레서블 사용 시에는 커스텀 에셋 번들 프로바이더를 구현하여 인스턴스 유지하며 번들을 내릴 수 있습니다. 🗑️
IL2CPP 메타데이터 최적화를 위해 매니지드 코드 스트리핑 레벨을 미디움 이상으로 설정하고 link.xml로 예외 처리하며, IL2CPP 코드 생성 옵션을 'Fast but Small'로 사용하고, 불필요한 패키지나 빌트인 모듈(예: UI 엘리먼트)을 제거해야 합니다. ✂️
메모리 단편화는 작은 할당이 많을 때 발생하며, 임시 할당을 최소화하고, 게임 데이터 파싱 전후로 프로파일링하여 파싱 방식이나 파서를 교체하는 것을 고려해야 합니다. 또한, 장면 전환 시 빈 장면을 삽입하여 이전 장면 리소스가 동시에 로드되는 것을 방지합니다. 🧩
유니티 프로파일러는 자체 부하가 있으므로 히칭 현상 진단 시 네이티브 프로파일러를 활용하고, GC 얼로케이션 콜스택은 일반 프로파일러에서도 확인할 수 있습니다. 📊
쉐이더 로드 히칭은 워밍업 콜이 불완전할 수 있으므로, 실제 사용하는 메시 구성으로 오프스크린 렌더링하는 것이 효과적입니다. 🖼️
복잡한 게임 오브젝트 인스턴스 생성 비용은 오브젝트 풀링으로 관리하고, 불가능할 경우 인스턴스 생성 시점을 분할하거나 InstantiateAsync를 활용하여 디시리얼라이즈 과정을 잡 시스템으로 분산할 수 있습니다. ⚙️
GC 컬렉트 히칭은 GC 얼로케이션을 최소화하여 호출을 지연하고, CPU 여유 시 인크리멘탈 GC를 사용하며, 완전히 비활성화하는 것도 고려할 수 있으나 메모리 관리 부담이 따릅니다. ♻️
렌더링 CPU 부하는 컬링과 드로우 단계로 나뉘며, SRP 배처 효율을 극대화하고, 컬링 부하가 높을 경우 카메라/라이트 거리별 레이어, LOD 그룹, 컬링 그룹 API를 활용하여 원거리/가려진 렌더러를 사전에 제거해야 합니다. 👁️
UI CPU 부하는 동적/정적 요소 분리, 레이아웃 시스템 사용 시 계층 구조 최소화 및 완료 후 비활성화, RectMask2D 사용 시 성능 저하 가능성(특히 텍스트 포함 시)을 고려하여 기존 마스크와 비교 테스트해야 합니다. 🎭
애니메이터는 컨트롤러 평가 비용을 줄이기 위해 불필요한 레이어/스테이트를 제거하고, 특정 이벤트(예: OnAnimatorIK)가 메인 스레드에서 동작하지 않도록 주의하며, 많은 애니메이터는 플레이어블 API를 통해 잡 시스템으로 묶어 처리할 수 있습니다. 🤖
스킨드 메시 스키닝 비용은 스킨 웨이트 확인, 카메라 밖 객체 스키닝 방지(Update When Offscreen 비활성화), GPU 배치드 버전 사용 시 대상 객체 수에 따른 성능 테스트가 필요합니다. 💪
카메라 자체의 CPU 부하를 줄이기 위해 불필요한 카메라를 제거하고, 필요한 경우 URP 렌더러 피처를 활용하여 컬링 결과를 재활용하거나 서브 카메라에 최적화된 렌더러를 지정할 수 있습니다. 📸
물리 업데이트는 고정 타임스텝으로 인해 프레임당 여러 번 발생할 수 있으므로, 타임스텝을 업데이트와 동기화하거나 시뮬레이션 모드를 변경하여 수동 호출 방식을 고려해야 합니다. ⏱️
레이캐스트 비용은 대상 수집 단계에서 발생하므로, distance와 LayerMask를 적절히 설정하여 대상 객체 규모를 줄이는 것이 중요합니다. 🎯
렌더러 바운딩 볼륨 갱신 부하는 많은 트랜스폼이 갱신될 때(예: 움직이는 코인) 발생하며, 루트 트랜스폼을 분산하거나 시각적 변화만 필요한 경우 버텍스 쉐이더 또는 DrawMesh API를 활용할 수 있습니다. 🌳
GPU 부하 요인 중 픽셀 오버드로우는 파티클(타이트한 지오메트리, 스프라이트 병합)과 UI(가려진 요소 비활성화, Canvas.alphaClip 확인)에서 최적화가 필요합니다. 🎨
쉐이더 개선은 네이티브 프로파일러로 픽셀 커버리지를 확인하여 우선순위를 정하고, 높은 정밀도의 인스트럭션 정밀도를 낮추거나 불필요한 텍스처 샘플링을 제거하며, 동적 분기는 A/B 테스트를 통해 성능 영향을 확인 후 결정해야 합니다. 🔬
마이크로 트라이앵글과 쿼드 오버드로우는 GPU의 쿼드 연산으로 발생하며, LOD를 통해 마이크로 트라이앵글을 줄이고, 얇고 긴 삼각형 대신 긴 경계면이 적은 메시 구성을 통해 쿼드 오버드로우를 방지할 수 있습니다. 모바일 환경에서 측정은 어렵지만, 다른 GPU 부하로 설명하기 힘든 경우 의심해 볼 수 있습니다. 🔺