Unity 검색

유니티의 어댑티브 퍼포먼스, 높은 수준의 품질과 원활한 프레임 속도 보장

2019년 4월 1일 테크놀로지 | 9 분 소요
공유

Is this article helpful for you?

Thank you for your feedback!

유니티는 GDC 2019 기조 연설에서 어댑티브 퍼포먼스(Adaptive Performance)에 대해 소개드렸습니다. 이제 이 기능이 프리뷰 버전으로 제공되며, 메가시티(Megacity)의 모바일 샘플에도 적용되어 여러분이 직접 어댑티브 퍼포먼스를 사용해볼 수 있습니다. 이 블로그에서는 어댑티브 퍼포먼스와 이를 사용자 프로젝트에 적용하는 방법에 대해 살펴보겠습니다.

PC나 콘솔 게임과는 달리, 모바일 디바이스에서 최상의 게임플레이 성능을 제공하려면 게임의 예술적 완성도를 높이면서도 쾌적환 환경에서 게임을 즐길 수 있는 균형이 필요합니다. 즉 디바이스의 성능을 최대치로 높일 경우 하드웨어 과도 사용으로 인해 스로틀링(throttling), 배터리 수명 단축, 일정하지 않은 성능이 초래되어 게임 실행에 문제가 발생할 수 있습니다. 개발자가 로우엔드(low-end) 디바이스부터 하이엔드(high-end) 디바이스까지 범위를 다양하게 고려하고 있다면 이 문제는 더욱 복잡해집니다.

오늘날 개발자는 이런 문제를 해결하기 위해 다양한 방법을 사용합니다. 가장 많이 사용되는 두 가지 접근 방법이 있는데, 한 가지는 그래픽 정확도와 프레임 속도를 희생시키고 게임이 모든 대상 하드웨어에서 최고의 성능을 발휘하도록 하는 것입니다. 또 다른 방법은 하드웨어 동작을 예측하려고 시도하는 것인데, 하드웨어 동작의 추세를 정확하게 측정할 수 있는 방법이 많지 않기 때문에 이 방법은 매우 어렵습니다.

어댑티브 퍼포먼스 작동 원리

어댑티브 퍼포먼스는 실시간으로 디바이스의 발열 및 게임 성능을 관리할 수 있는 더 나은 방법을 제공함으로써 게임의 실시간 성능 및 품질 설정을 사전에 조정하여 디바이에 과도한 부담을 주지 않으면서 하드웨어를 활용할 수 있습니다. 결과적으로 프레임 속도를 예측하고 디바이스의 발열을 분산시켜 디바이스 배터리 수명을 유지하면서 플레이어가 더 오랜 시간 동안 더욱 만족도가 높은 플레이어 환경을 즐길 수 있습니다.

게임을 더 역동적이고 유연하게 만들 수 있는 도구를 하드웨어에 구현하여 개발자는 깊은 통찰력을 새롭게 얻을 수 있고, 이를 통해 모바일 디바이스를 사용하는 플레이어에게 가장 매끄럽고 높은 성능의 게임 경험을 선사할 수 있습니다. 또한 높은 클럭 속도로 실행할 시기나 스로틀링 현상을 피하기 위해 조정해야 할 요소 등과 같이 일반적으로 운영체제가 결정하는 사항을 여러분이 직접 제어할 수 있습니다.

유니티는 GDC 2019에서 이 기능에 대한 발표를 여러 번 진행했습니다. 여기에서 슬라이드 발표 내용을 확인해보세요.

이 콘텐츠는 Targeting Cookies 카테고리를 수락해야만 동영상을 시청할 수 있도록 허용하는 타사 제공업체에서 호스팅합니다. 이러한 제공업체의 비디오를 보려면 쿠키 환경 설정에서 Targeting Cookies 카테고리를 수락하시기 바랍니다.

삼성과 협업하여 어댑티브 퍼포먼스 구현

유니티는 이 솔루션이 결실을 맺을 수 있도록 세계 최대의 Android 모바일 디바이스 제조업체인 삼성과 협력 관계를 맺었습니다. 삼성의 GameSDK를 기반으로 구축된 어댑티브 퍼포먼스는 삼성 갤럭시 S10과 갤럭시 폴드 등 삼성 갤럭시 디바이스에서 최초로 공개되며, 추가로 올해 출시될 삼성 갤럭시 디바이스에서도 지원됩니다.

초기 결과

GDC 2019 유니티 기조 연설 에서 공개된 아래 자료는 어댑티브 퍼포먼스가 적용된 새로운 삼성 갤럭시 S10에서 메가시티를 재생할 때 높은 프레임 속도를 얼마나 지속적으로 유지되는지 보여줍니다.

빨간색 선은 어댑티브 퍼포먼스를 사용하기 전 메가시티의 프레임 속도를, 파란색 선은 어댑티브 퍼포먼스를 사용한 후의 결과를 나타냅니다. 어댑티브 퍼포먼스를 적용하면 데모가 훨씬 더 오랜 시간 동안 30fps의 속도로 실행되며 훨씬 안정적입니다.

메가시티를 샘플로 선택한 이유

메가시티는 수백만 개의 엔티티를 갖춘 인터랙티브한 미래 도시로, Unity가 현세대 모바일 하드웨어에서 가장 복잡한 프로젝트도 실행할 수 있음을 잘 보여줍니다. 또한 이를 통해 ECS(Entity Component System, 엔티티 컴포넌트 시스템), 네이티브 컬렉션, C# 잡 시스템 및 버스트 컴파일러를 포함하는 “고성능 최적화(Performance by Default)”를 슬로건으로 내건 모든 프로젝트에 적용되는 DOTS(Data-Oriented Technology Stack, 데이터 지향 기술 스택)의 최신 발전 내용을 볼 수 있습니다. 메가시티는 Unite Los Angeles 2018에서 처음 선보였으며, GDC 2019 기간 중에 데스크톱용으로 출시되었습니다.

메가시티는 어댑티브 퍼포먼스를 위한 샘플 제작을 시연하기에 가장 좋은 프로젝트입니다. 게임을 환경에 따라 유연하게 실시한 조정할 수 있어 하드웨어를 효율적으로 활용할 수 있는 많은 옵션을 제공하기 때문입니다. 어댑티브 퍼포먼스는 메가시티의 기초를 구축하는 데 사용된 DOTS의 원리와 잘 맞도록 확장성을 고려하여 적용되었습니다.

모바일 버전의 메가시티는 450만 개의 메시 렌더러, 20만 개의 건물 컴포넌트, 10만 개의 오디오 소스 및 600만 개 이상의 엔티티를 포함하고 있어 어댑티브 퍼포먼스의 성능을 선보이기에 가장 이상적인 프로젝트입니다.

메가시티에 적용된 어댑티브 퍼포먼스 작동 원리

Unity 패키지 관리자를 통해 어댑티브 퍼포먼스를 설치한 후 디바이스에 프로젝트를 빌드하면, Unity에서 삼성 GameSDK 하위 시스템을 프로젝트에 자동으로 추가합니다. Unity는 런타임 동안 지원 디바이스에 어댑티브 퍼포먼스 관리자(Adaptive Performance Manager)를 생성하고 실행하여 해당 모바일 디바이스의 발열 상태에 대한 피드백을 제공합니다. 어댑티브 퍼포먼스 관리자의 이벤트를 수신하거나 정보를 쿼리하여 런타임 동안 실시간으로 대응할 수 있습니다. 아무런 행동도 취하지 않는 경우에는 콘솔에만 상태를 알려줍니다.

예를 들어, 제공되는 API를 이용하여 디바이스의 발열 추세(thermal trend)나 이벤트에 반응하는 애플리케이션을 생성할 수 있습니다. 이를 통해 더 오랜 시간 동안 프레임 속도를 유지하면서 서멀 스로틀링이 시작되기도 전에 스로틀링을 피할 수 있습니다. 메가시티의 어댑티브 퍼포먼스 샘플 제작 시 원활한 프레임 속도를 위해 세 가지 다른 방법을 사용했습니다.

  • 병목 현상을 없애기 위해 CPU 및 GPU를 중간 수준에서 시작해서 점진적으로 증가시킴으로써 에너지 소비량을 적게 유지할 수 있었습니다.
  • 디바이스가 스로틀링 상태에 가까워지면 품질 설정을 조정하여 발열 로드를 줄일 수 있었으며 결과적으로 LOD 수준을 낮추기로 결정했습니다.
  • 또한 스로틀링 상태에 가까워질 때 목표 프레임 속도를 낮췄습니다.
  • 목표 프레임 속도에 도달했을 때 온도가 감소 중이라면 LOD 수준과 목표 프레임 속도를 높이고 CPU 및 GPU 수준을 다시 낮췄습니다.

이러한 기능을 통해 시간이 지날수록 게임이 더욱 원활한 성능을 구현할 수 있습니다. 디바이스의 발열 추세를 면밀히 관찰하면 성능 설정을 동적으로 조정하여 스로틀링 현상을 완전히 막을 수 있습니다.

여기에서 메가시티 모바일 샘플 프로젝트를 다운로드해서 위 내용을 직접 확인해보세요. 메가시티 관련 피드백 또는 문의는 이 포럼 스레드를 방문해주시기 바랍니다.

어댑티브 퍼포먼스 관리자

이 패키지의 핵심은 Unity가 시작 시 생성하는 어댑티브 퍼포먼스 관리자로, 발열 및 성능 이벤트 알림에 쉽게 액세스하고 받아 볼 수 있습니다. 아래 예제는 MonoBehavior의 Start 함수에서 IAdaptivePerformance 인터페이스를 사용하여 어댑티브 퍼포먼스 관리자에 액세스하는 방법을 보여줍니다.


private IAdaptivePerformance ap = null;

void Start()
{
    ap = Holder.instance;
}

발열 이벤트

Unity는 디바이스의 발열 상태에 변화가 있을 때마다 발열 이벤트(thermal event)를 보냅니다. 이때 중요한 상태는 스로틀링이 임박했을 때와 스로틀링이 발생했을 때입니다. 아래 예제에서 ThermalEvent를 수신하여 GPU 로드를 감소하도록 돕는 lodBias를 줄이거나 늘릴 수 있습니다.


using UnityEngine;
using UnityEngine.Mobile.AdaptivePerformance;

public class AdaptiveLOD : MonoBehaviour
{
    private IAdaptivePerformance ap = null;

    void Start() {
        if (Holder.instance == null)
            return;

        ap = Holder.instance;

        if (!ap.active)
            return;

        QualitySettings.lodBias = 1;

        ap.ThermalEvent += OnThermalEvent;
    }

    void OnThermalEvent(object obj, ThermalEventArgs ev) {
        switch (ev.warningLevel) {
            case PerformanceWarningLevel.NoWarning:
                QualitySettings.lodBias = 1;
                break;
            case PerformanceWarningLevel.ThrottlingImminent:
                QualitySettings.lodBias = 0.75f;
                break;
            case PerformanceWarningLevel.Throttling:
                QualitySettings.lodBias = 0.5f;
                break;
        }
    }
}

참고로 lodBias 값을 1 미만으로 줄이면 대부분의 경우 시각적인 영향을 미치며, LOD 오브젝트가 튀는 현상(오브젝트 파핑, object-popping)이 일어날 수 있지만, 이는 게임에 필요하지 않은 그래픽 로드를 줄이는 쉬운 방법 중 하나입니다. 게임의 그래픽스와 동작을 처리하는 방법을 미세 조정하기 위해 더욱 구체적인 결정을 내려야 하는 경우에는 병목 현상 이벤트가 매우 유용합니다.

CPU GPU 성능 수준

모바일 디바이스에서 CPU 및 GPU는 특히 게임 실행 시 전력 사용량의 상당 부분을 차지합니다. 일반적으로 운영체제가 CPU와 GPU에 사용되는 클럭 속도를 결정합니다.

CPU 코어와 GPU는 최대 클럭 속도에서 실행될 때 효율이 떨어집니다. 게임을 높은 클럭 속도로 실행하면 모바일 디바이스가 쉽게 과열되고 운영체제가 CPU와 GPU의 빈도를 스로틀링하여 디바이스를 냉각시킵니다.

다음 프로퍼티를 사용해 최대 허용 클럭 속도를 제한하여 이러한 현상을 피할 수 있습니다.

  • IAdaptivePerformance.cpuLevel

  • IAdaptivePerformance.gpuLevel

애플리케이션은 현재 성능 요구사항에 대해 인식한 특수 정보를 바탕으로 해당 프로퍼티를 설정할 수 있으며, 시나리오를 기반으로 수준을 높일 것인지 낮출 것인지를 결정할 수 있습니다.

  • 애플리케이션이 이전 프레임에서 목표 프레임 속도에 도달했는가?
  • 애플리케이션이 게임 내 씬(in-game scene) 또는 메뉴에 있는가?
  • 앞으로 리소스가 많은 씬이 등장하는가?
  • 다가오는 이벤트가 CPU 또는 GPU에 많은 부하를 주는가?
  • 높은 CPU/GPU 수준을 요구하지 않는 광고를 게재하는가?

public void EnterMenu(){
    if (!ap.active)
        return;

    // Set low CPU and GPU level in menu
    ap.cpuLevel = 0;
    ap.gpuLevel = 0;
    // Set low target FPS
    Application.targetFrameRate = 15;
}

public void ExitMenu(){
    // Set higher CPU and GPU level when going back into the game
    ap.cpuLevel = ap.maxCpuPerformanceLevel;
    ap.gpuLevel = ap.maxGpuPerformanceLevel;
}

성능 병목 현상을 초기에 알리는 경고 시스템

어댑티브 퍼포먼스 관리자에서 GPU 바운드, CPU 바운드 또는 “프레임 속도 바운드(frame-rate bound)”인지 알려주는 성능 병목 현상 이벤트를 수신하도록 할 수 있습니다. 프레임 속도 바운드란 게임이 Application.targetFrameRate에 의해 제한되는 것을 의미하며, 이 경우 애플리케이션의 성능 요구사항을 낮추는 것을 고려해야 합니다.

GPU 프레임타임 드라이버는 백그라운드에서 병목 현상에 대한 의사 결정을 주관하며, 어댑티브 퍼포먼스 관리자를 통해 쿼리가 가능합니다. 이 드라이버는 마지막 프레임에서 GPU가 소비한 하드웨어 시간을 모니터링합니다. 현재로서 CPU 시간은 Unity 내부의 하위 시스템을 합산하여 계산됩니다. 게임 및 시나리오에 따라, 게임이 CPU 또는 GPU 바운드일 경우 발열 상태 변화에 따라 다르게 대응하도록 설정할 수 있습니다.


void OnBottleneckChange(object obj, PerformanceBottleneckChangeEventArgs ev) {
    switch (ev.bottleneck) {
        case PerformanceBottleneck.TargetFrameRate:
            if (ap.cpuLevel > 0) {
                ap.cpuLevel--;
            }
  	     if (ap.gpuLevel > 0) {
                ap.gpuLevel--;
            }
            break;
        case PerformanceBottleneck.GPU:
            if (ap.gpuLevel < ap.maxGpuPerformanceLevel) {
                ap.gpuLevel++;
            }
            break;
        case PerformanceBottleneck.CPU:
            if (ap.cpuLevel < ap.maxCpuPerformanceLevel) {
                ap.cpuLevel++;
            }
            break;
    }
}

물론 게임을 최적화하는 방법은 다양합니다. 위에서 보여드린 샘플과 메가시티 샘플은 이중 일부만 보여드렸습니다. 궁극적으로 최적화 방법은 자신의 게임에 가장 적합한 것이 무엇인지에 따라 달라질 수 있습니다. 자세한 내용은 패키지 기술 자료를 참조하세요.

어댑티브 퍼포먼스의 미래

이 모든 것은 시작에 불과합니다. 유니티는 어댑티브 퍼포먼스에 지속적으로 투자하여 점점 더 많은 기능을 추가하고 더 많은 디바이스를 지원할 예정입니다. 현재 패키지에는 로우 레벨의 API가 포함되어 있지만, 이미 DOTS와 호환되는 하이 레벨의 컴포넌트 기반 API를 준비 중으로, 향후에는 Unity 프로젝트에서 더욱 쉽게 성능을 조정할 수 있게 됩니다. 자세한 내용은 계속 지켜봐 주시기 바랍니다.

지금 시작하기

어댑티브 퍼포먼스 프리뷰 버전은 Unity 2019.1(베타)에서 Unity 패키지 관리자를 통해 사용할 수 있습니다. 여기에서 액세스할 수 있습니다. 어댑티브 퍼포먼스 관련 최신 정보 및 다른 개발자의 사용 방법을 확인하거나 질문 혹은 의견을 게시하려면 포럼을 방문해 주시기 바랍니다.

2019년 4월 1일 테크놀로지 | 9 분 소요

Is this article helpful for you?

Thank you for your feedback!