Unity 검색

Unity 워크플로 속도를 향상하는 방법

2021년 7월 5일 엔진 & 플랫폼 | 20 분 소요
Black gradient background with a overlay of white graph lines and the words "2021.2 Feature Preview"
Black gradient background with a overlay of white graph lines and the words "2021.2 Feature Preview"
공유

Is this article helpful for you?

Thank you for your feedback!

크리에이티브 작업에는 빠른 프로토타이핑이 핵심입니다. 이번 포스팅에서는 에셋을 임포트하는 것부터 플레이 가능한 게임을 빌드하고 배포하는 것까지, 제작 수명 주기 전반에서 필요한 작업을 빠르게 반복할 수 있도록 Unity 에디터의 핵심 기능을 최적화하는 방법을 알아보겠습니다.

프로토타이핑에서 제작 단계로 넘어가고 많은 콘텐츠를 추가하면서 프로젝트가 확장하게 되면 에디터의 성능이 팀원들의 생산성에 중요한 역할을 차지합니다. 따라서 유니티는 로드맵 포스팅에서 다룬 바와 같이 2021년의 핵심 목표 중 하나로 성능과 반복 속도의 향상을 설정했습니다.

에셋 워크플로: 임포트, 생성, 빌드, 배포, 로드

대부분의 콘텐츠 유형에서 Unity 에디터는 에셋의 소스 파일에 있는 데이터를 게임 또는 실시간 애플리케이션에서 사용할 수 있는 포맷으로 전환해야 합니다. Unity에서 임포트를 완료하면 전환된 파일과 관련 데이터가 에셋 데이터베이스에 저장됩니다. 임포트 후에 임포터에서 사용한 파일이 디스크에서 변경된 경우 Unity에서 에셋 데이터베이스를 새로고침합니다. Unity에서 스크립트 변경을 감지하면 C# 도메인이 리로드됩니다. 프로젝트를 타겟 플랫폼으로 배포할 준비가 되면 Unity의 빌드 시스템에서 프로젝트를 바이너리 파일로 패키징하여 원하는 플랫폼으로 배포하고 실행할 수 있도록 지원합니다.

Asset workflow

에셋 데이터베이스는 모든 단계에 걸쳐 확장 가능하고 안정적인 고성능 에셋 임포트 파이프라인을 구현하는 핵심 기술입니다.

하지만 임포터 및 압축 툴에서 핵심 에디터 코드 및 빌드 파이프라인에 이르기까지 다양한 요소가 에디터의 반복 시간에 영향을 미치게 됩니다. 이번 블로그 포스팅을 작성하면서, 해당 분야의 유니티 전문가들을 만나 사용자들이 Unity 2021.2를 최대한 효과적으로 활용하도록 지원하기 위한 개선 사항을 자세히 들어 보았습니다.

에디터 시작 시간 최적화

프로젝트 시작 단계에서는 에셋 데이터베이스가 Unity 프로세스의 대부분을 차지합니다. 따라서 에셋 데이터베이스 코드를 최적화하면 실행 시간을 얼마나 단축할 수 있는지를 확인해 보고자 했습니다. 에셋 데이터베이스 팀의 시니어 소프트웨어 엔지니어인 하비에르 에이버드와 조나스 드루센은 90만 개의 에셋이 포함된 가상 테스트 프로젝트를 시작으로 벤치마킹 프레임워크를 통해 에디터 시작 시간과 관련된 많은 최적화와 개선 사항을 이끌어냈습니다. 또한 에셋 데이터베이스에 대한 변경 사항이 Unity 에디터의 성능에 어떤 영향을 미치는지 알려주는 지표를 수집하는 과정을 자동화하는 내부 툴도 함께 개발했습니다.

하비에르는 “많은 노력이 필요하지 않은 경우도 있었지만, 창의적인 사고를 발휘해야 하는 상황도 많았습니다. 매주 테스트 프로젝트의 시작 시간을 15초 가량 단축한 다음 실제 프로젝트 22개를 가지고 변경 사항이 유효한지도 확인했습니다. 대규모 프로젝트에 맞춘 최적화로 인해 그보다 작은 실제 프로젝트의 성과가 저조해지는 불상사가 없도록 하기 위해서였죠”라고 밝혔습니다. 예를 들어, 에셋 데이터베이스 팀은 스레드 또는 정렬 중의 메모리 할당을 줄이고 모든 프로젝트 파일 및 폴더에 대해 병렬 수집을 도입했습니다. Unity 2021.2에서 팀은 90만 개의 텍스트 에셋이 포함된 프로젝트의 에디터 시작 시간을 기존의 3분 36초에서 1분 17초로 단축하고, 소규모 프로젝트의 실행 시간도 평균 8.7% 단축했습니다.

임포트

Import Activity 창

하비에르는 또한 Import Activity 창을 개발하여 에셋이 임포트된 이유, 프로세스에 소요된 시간, 종속성으로 인해 임포트에 민감한 에셋에 대한 정보를 확인할 수 있게 했습니다. 자세한 내용은 이 포럼 포스팅을 참조하세요.

모델 및 텍스처 임포트 속도 개선

일반적으로 모델 및 텍스터를 임포트하는 작업은 에디터에서 수행되는 작업 중 가장 큰 부분을 차지합니다. 아래 이미지는 사자의 서: 환경(Book of the Dead:Environment) 프로젝트의 모든 텍스처, 모델, 프리팹 및 씬에 대한 임포트 테스트 결과입니다.

Image displaying BOTD Assets import time (PC platform), in seconds and the comparison between 2020 and 2021

테스트 프로젝트는 346개의 텍스처, 133개의 모델, 214개의 프리팹, 6개의 씬을 포함하여 총 2.25GB의 소스 에셋 데이터로 구성되었습니다. Windows, AMD ThreadRipper 1950X(16 스레드) 및 SSD 저장 장치로 구성된 컴퓨터에서 각 버전의 Unity(Unity 2020.3.10, 2021.1.9 및 2021.2 알파(a19))를 사용하여 실행 시간을 측정했습니다.

그 결과 기본적으로 2021.2 알파 버전에서 모든 에셋을 114초 만에 임포트했으며, 이는 2021.1 버전과 비교하여 1.27배 빠른 기록입니다. 4개의 에셋 임포트 워커 프로세스로 병렬 에셋 임포트를 활성화하면 77초 만에 에셋 임포트를 완료할 수 있습니다. 해당 설정은 Project Settings → Editor → Refresh에서 찾을 수 있습니다.

Build Settings 창에 있는 Force Fast Compressor 옵션을 사용하여 반복 시간을 단축하면 모든 에셋을 38초 만에 임포트할 수 있습니다. 2021.1 버전과 비교하면 3.8배나 빠른 기록입니다. 이렇게 하면 텍스처의 크기나 포맷을 변경하지 않고도 적은 노력으로 최적의 압축된 텍스처 픽셀을 만들어 낼 수 있습니다.

모델 임포트 속도 개선

최적화 팀의 리차드 케틀웰은 2021년 로드맵에 따라 모델 임포트 속도를 개선하는 것에 집중했습니다. 리차드는 “다양한 문제점과 그에 따른 솔루션 중 몇 가지를 취사선택했습니다”라며, “예를 들어, 메시의 크기가 크면 시간이 많이 걸리는 버텍스별 메모리 할당 방식 대신에 총 필요 메모리를 미리 계산한 후 하나의 블록에 할당하는 알고리즘이 있었습니다. 또한, 임포트 작업은 파일에 있는 모든 메시, 버텍스, 애니메이션 또는 머티리얼에 대해 수행됩니다. 독립적인 부분을 파악하고 해당 부분을 병렬로 실행하게 되면 임포트 속도를 크게 개선할 수 있습니다”라고 밝혔습니다.

그리고 “임포트 단계에서만 잠시 필요한 메모리에 더 빠른 메모리 할당자를 사용하여 모든 부분을 개선할 수 있었습니다”라며 “문제가 발생한 모델을 공유해 주신 아티스트 분들께 감사의 말씀을 드리고 싶습니다. 좋은 콘텐츠를 제공해 주신 덕분에 테스트를 수행할 수 있었습니다”라고 감사의 뜻을 표했습니다.

이제 Unity 2021.2에서는 여러 개의 메시를 포함하는 파일에서 노멀, 탄젠트 및 라이트맵 UV를 병렬로 생성할 수 있습니다. 임포트에 33분이 걸렸던(라이트맵 UV를 생성하는 데만 30분 소요) 특정 파일의 경우 전체 임포트 시간을 무려 66% 빠른 11분으로 줄일 수 있었습니다. 여러 개의 메시를 포함하는 모델 파일은 모두 이와 같은 이점을 누릴 수 있습니다. 기존의 단계가 오래 걸렸기 때문에 해당되는 파일에 대한 임포트 속도가 크게 개선될 것으로 예상됩니다.

또한, 다음과 같은 모델 임포트 단계에 멀티스레딩을 사용했습니다.

  • FBX 애니메이션 임포트
  • 버텍스 캐시 옵티마이저 실행
  • 메시 삼각측량(N-Gon을 삼각형으로 변환)
  • SketchUp 버텍스 처리

텍스처 임포트 최적화

QoL 팀은 프로세스의 텍스처 임포트 부분을 맡아 2021.1에서 선보인 개선 사항을 꾸준히 발전시키고 있습니다. 2021.2에서 QoL 팀은 다시금 ASTC 컴프레서를 업데이트하여 속도를 30% 더 향상하고 다양한 CPU 간의 신뢰성을 개선했습니다. 또한, BC7 압축은 약 2~3배 정도 더 빨라졌습니다. 

Build Settings의 Force Fast Compressor 옵션 또한 QoL 팀의 이니셔티브 중 하나입니다. 아라스 프랑케비치우스는 “텍스처 품질에 대해 크게 중점을 두지 않는다면, Force Fast Compressor 옵션을 사용하여 텍스처 압축에 많은 노력을 들이지 않도록 설정하거나 전체적으로 최대 텍스처 임포트 크기를 제한하도록 설정할 수 있습니다”라고 설명하며, “압축 결과물에 결함이 약간 더 생길 수 있다는 단점이 있지만, 기존의 20분에서 훨씬 단축된 2분 이내로 2GB의 텍스처를 Android ASTC 포맷으로 임포트할 수 있게 되었습니다. 빠르게 반복 작업을 수행해야 하는 경우에는 이 방법이 좋죠”라고 덧붙였습니다.

Graph displaying the BOTD switch to Android+ASTC, in seconds comparison from 2020.3 to 2021.4

더욱 빠른 에디터 작업 속도로 중단 없는 워크플로 실현

에디터의 계층 구조에서 대형 씬을 여는 시간을 90% 이상 단축

씬 루트(계층 구조 뷰에서 최상위 수준에 있는 게임 오브젝트)는 링크드 리스트에 순서대로 저장되어 있어 로드와 병합에 많은 비용이 들었습니다. 이전에 에디터에서 씬을 열면 각 루트 오브젝트가 차례대로 이 리스트에 추가되었습니다. 씬에서 로드될 때마다 이 리스트에 항목이 추가되고, 각각의 새로운 게임 오브젝트는 링크드 리스트를 확인하여 새로운 항목을 찾아야 했습니다. 이제는 새롭게 추가되는 루트 오브젝트로 구성된 dynamic_array를 저장하여 리스트가 필요한 경우에만 정렬하여 링크드 리스트로 전환합니다. 결론적으로 에디터에서 테스트 씬을 여는 데 걸리는 시간을 17초에서 1.45초로 단축해 무려 90%의 시간 단축을 이루었습니다.

Graph displaying the time to open a scene in editor with a graph comparing before optimization and after optimization on a scale of 10000 to 50000

간단한 변화로 대규모 프로젝트를 지원하는 Unity

성능 최적화 팀의 주요 업무 중 하나는 고객과 협업하고 내부의 대규모 제작 과정에서 에디터 작업의 속도를 높일 방법을 찾는 것입니다. 몇 초도 안 되는 대기 시간이라 할지라도 게임의 규모가 커지면 문제로 발전할 수 있습니다. 

피터 홀은 Unity 2021.2에서 이 부분을 개선하기 위해 다양한 시도를 했습니다. 피터가 담당한 속도 개선 작업 중 하나는 대규모 씬에서 다수의 항목을 드래그 및 선택하는 워크플로를 최적화하는 작업이었습니다. 벤치마크로 사용한 내부 프로젝트의 경우 대규모 씬 하나에 78초가 소요되는 문제가 있었습니다. 피터는 “프로파일러로 캡처해 본 결과, GameObjectTreeViewDataSource.RevealItems에서 호출된 BaseHierarchyProperty::Find에서 대부분의 시간이 소비된 것을 알 수 있었습니다. 계층 구조의 부모 오브젝트를 루트로 다시 옮기는 작업에서 선택 항목을 각각 하나씩 옮기는 것이 문제였습니다. 그래서 IHierarchyProperty.FindAllAncestors를 사용하여 작업에 소요되는 시간을 약 50밀리초로 단축해 1,400배의 속도 향상을 이루었습니다”라고 설명했습니다.

대규모 프로젝트의 다른 처리 과정에서도 에디터 워크플로의 속도 향상이 이루어졌습니다. 예를 들어, 새로운 머티리얼을 생성하는 작업은 2배 더 빨라졌고 씬에서 모든 오브젝트를 선택하는 작업은 1.6배 빨라졌으며 게임 오브젝트를 복사/붙여넣기하는 작업은 50% 더 빨라졌습니다.

빌드

테스트 및 최적화 단계에 들어서면 기기의 반복 속도가 중요해집니다. 따라서 유니티는 빌드 파이프라인을 전반적으로 최적화하기 위해 많은 시간과 노력을 쏟고 있습니다. 일례로 유니티는 Unity 2021.2에서 스크립터블 빌드 파이프라인과 빌드 캐시의 속도 향상을 이루었습니다.

플레이어 빌드 시간이 전체 프로젝트 크기가 아닌 점진적인 변경 사항의 크기에 따라 조정되도록 하는 것이 빌드 영역에서의 주안점 중 하나입니다. 최근 유니티는 Unity를 빌드하는 방식 자체를 개선하였고, 이제 플레이어 빌드 및 스크립트 컴파일에 동일한 툴을 제공하고 있습니다. 그 결과 Unity 2021.2 베타에서는 증분 C# 스크립트 컴파일을 지원하는 솔루션을 통해 Windows, macOS, Android, Linux 및 WebGL에 점진적 플레이어 빌드 지원을 제공할 수 있게 되었습니다. 향후 Unity 버전에서는 이러한 개선 사항을 나머지 플랫폼에도 추가하려고 합니다.

스크립팅 팀의 요나스 엑터호프는 “플레이어를 빌드할 때 Unity는 많은 작업을 합니다. 먼저, 모든 씬과 관련 에셋, 그리고 게임 관리자를 데이터 파일로 묶어 플레이어 데이터를 빌드합니다. 이 작업은 네이티브 C++ 코드로 이루어집니다”라고 설명하며, “데이터 빌드를 완료하면 포스트 프로세싱 메서드를 호출합니다. 이 메서드는 플랫폼마다 다른 관리되는 코드입니다. 포스트 프로세서에서 수행하는 작업은 플랫폼마다 다르지만, 일반적으로 모든 플레이어 바이너리 및 관련 파일을 최종 대상으로 복사하고, IL2CPP에서 생성한 코드를 네이티브 라이브러리로 컴파일하며, 플랫폼별 압축 및 플랫폼별 패키징과 같은 작업이 포함됩니다. 이러한 포스트 프로세싱 로직을 새로운 빌드 시스템에 추가했습니다”라고 덧붙였습니다. 이 시스템은 각 빌드 단계의 입력과 출력을 이해하고 입력과 출력 간의 종속성을 이해하기 때문에, Unity에서는 재실행이 필요한 단계만을 재실행하고 가능한 경우 병렬로 작업을 실행할 수 있습니다.

IL2CPP 속도 개선

또한, Build Settings 메뉴의 새로운 IL2CPP Code Generation 옵션을 사용하면 풀제네릭(full-generic) 공유를 통해 코드를 최대 50% 줄일 수 있습니다. 이를 통해 IL2CPP 빌드 시간이 단축되고 실행 파일의 크기가 줄어듭니다. 서로 다른 코드 생성 방법으로 인해 런타임 성능에 다소 영향을 미칠 수 있으므로, 이 옵션은 팀 내 반복 작업에 소요되는 시간을 일시적으로 줄이기에 적합합니다. 이 옵션을 사용해본 후 프로젝트 진행 속도에 어떤 영향을 미치는지 이 포럼 스레드에서 알려 주세요.

2020.3 버전에서는 IL2CPP를 대대적으로 수정하여 다중 코어를 활용한 플레이어 빌드용 C++ 코드 생성이 가능하도록 했습니다. IL2CPP 팀의 마이클 부히스는 “기존의 코드를 토대로 작업한 결과 설계를 변경하는 데 제약이 있었습니다. 그래서 코드 베이스 전반에 사용되었던 정적 필드를 제거하고, 병렬화가 쉬운 분할 정복(Divide and Conquer) 패턴으로 리팩터링했습니다. 내부 API를 리팩터링하여 병렬 및 직렬 전환 모드를 유지하면서, 위험도가 낮은 방법을 선택했습니다. 그럼에도 강도 높은 성능 테스트 씬을 생성하고 한 달간의 테스트를 거친 후에야 병렬 전환을 기본값으로 설정했습니다”라고 밝혔습니다. 코어 활용도 및 최적화를 개선한 결과 2021.1 버전에서 전환 시간이 더욱 감소하는 결과가 나타났습니다.

2021.2 버전에서 IL2CPP 팀은 많은 비용이 소요되는 코드 전환 단계인 제네릭 컬렉션을 병렬화했습니다.마이클은 “최적화를 극대화하기 위해 Cecil을 직접 제작한 새로운 데이터 모델로 교체했습니다. 다양한 소규모 최적화까지 더해져 2021.1 버전에 비해 2021.2 버전에서 IL2CPP 코드 전환이 약 2배 정도 빨라졌습니다”라고 설명했습니다.

Graph 2

이처럼 빌드 속도를 개선하면 특히 모바일 개발자에게 큰 영향을 미칩니다. 예를 들어, ARMv7 및 ARM64 플랫폼을 대상으로 Unity 2020 LTS의 비증분 빌드를 사용하여 최신 2D 예제 프로젝트인 Dragon Crashers를 빌드하는 데 간단한 스크립트 변경 사항에도 91초가 걸렸습니다. 반면 Unity 2021.2에서 새로운 증분 빌드 툴을 사용한 결과 절반도 되지 않는 44초밖에 걸리지 않았습니다.

메모리 관리에 효율적인 에셋 번들 로딩

Image of a virtual underwater scene with a hand holding a recording camera in the bottom right corner
Subnautica 프로젝트에는 5,199개의 에셋 번들이 있습니다.

모바일 개발자에게 동적 콘텐츠 전달 기술이 어느 때보다 중요해지면서, 런타임 시 에셋을 로드하고 보관하는 데 에셋 번들이 더욱 중요한 역할을 하게 되었습니다. 하지만 각 에셋 번들을 동시에 로드할 때마다 런타임 플랫폼별로 14k에서 128k까지 고정 메모리가 소모됩니다.

올해 봄, 에셋 파이프라인 팀의 크리스틴 필라와 조셉 쉐인버그가 이 문제를 해결하기 위해 나섰습니다. 크리스틴은 “각 에셋 번들에 전용 캐시를 두는 대신에 공유 페이지 풀을 도입했습니다”라고 밝히며, “에셋 번들을 많이 활용하는 실제 프로젝트를 통해 메모리 문제가 얼마나 개선되었는지 확인하고자 했습니다. 그래서 이전에 Unknown Worlds에서 진행한 Subnautica 최적화 작업을 지원했던 유니티 프로페셔널 서비스 팀의 패트릭 드바니에게 도움을 요청했죠”라고 덧붙였습니다. 1,616개의 에셋 번들을 로드한 상태에서 공유 페이지 풀은 215.7MB의 초기 오버헤드를 12.9MB로 감소시켜 94%의 감소 효과를 보였습니다. 

에셋 파이프라인 팀은 또한 메모리 할당량을 관리하는 간단한 공개 API(AssetBundle.memoryBudgetKB)를 도입했습니다.

Diagram with a black background showing how the pooled filecacher system works with assetbundle 1, assetbundle 2, and assetbundle pointing back to the memory cache block pool

향후 계획

사용자들은 빠른 반복 작업을 유니티의 가장 큰 장점 중 하나로 꼽습니다. 유니티는 고객 프로젝트에서 내부 제작에 이르기까지 팀 생산성을 저해하는 병목 현상에 대한 보고를 예의 주시하고 있으며, 에디터의 반복 작업 시간에 영향을 주는 빌트인 및 패키지 기능의 효과를 모니터링하기 위한 탁월한 툴도 개발하고 있습니다. 유니티는 내부 개발 주기 동안 에디터의 반복 작업 시간에 대한 주요 성능 지표를 눈여겨보았습니다. 향후 릴리스 버전에서는 프로젝트의 크기에 상관없이 작업 속도가 훨씬 더 단축될 것으로 예상됩니다.

에셋 임포트 분야에서의 장기 전략은 온디맨드 방식으로 에셋을 로딩하는 것으로, 이를 구현하면 Unity에서 원하는 에셋을 필요할 때만 임포트할 수 있습니다. 또한, 지원하는 모든 플랫폼에서 증분 빌드를 사용할 수 있도록 변경하고 있으며, iOS의 경우 곧 지원될 예정입니다.

위와 같이 유니티에서 속도 개선에 집중하기를 원하는 특정 영역이 있다면 파이프라인 및 통합 로드맵의 관련 영역에 제안 사항을 전달해 주세요. 

Unity 2021.2 베타 버전을 사용하고 피드백을 공유해 주세요

속도 개선에 주력한 Unity 2021.2를 사용하고 프로젝트 워크플로가 얼마나 개선되었는지 알려 주세요. 이번 릴리스는 현재 베타 버전으로 이용할 수 있으며, 모든 개선 사항에 대한 자세한 개요는 베타 릴리스 블로그 포스팅에서 확인할 수 있습니다. Unity 2021.2 포럼에서 의견을 공유해 주세요. 특히 모델 및 텍스처 임포트새로운 IL2CPP Code Generation 옵션을 사용해보고 피드백을 공유해 주세요. traVRsal의 개발자인 로버트 웨트졸드를 비롯하여 피드백을 공유해 주신 알파 테스터 여러분께 깊은 감사의 말씀을 드립니다.

Unity와 관련된 전반적인 경험을 공유하고 Unity의 미래를 함께 만들어 나가고 싶다면 Unity Pulse에 가입하세요. Unity Pulse는 유니티의 새로운 연구 플랫폼이자 커뮤니티로 설문 조사, 여론 조사, 회의, 인터뷰 및 그룹 토론을 통해 리소스의 우선순위를 결정합니다.

2021년 7월 5일 엔진 & 플랫폼 | 20 분 소요

Is this article helpful for you?

Thank you for your feedback!

관련 게시물