무엇을 찾고 계신가요?
Hero background image
Unity UI 최적화 팁
캔버스 및 레이아웃 그룹 분할, UI 개체 풀링 등에 대한 팁을 통해 UI를 완전히 최적화하는 방법을 알아보세요.

이 페이지는 PC 및 콘솔 게임을 최적화하는 방법에 대한 심층적인 안내를 제공하는 여러 페이지 중 하나입니다. 전체 컬렉션은 무료 전자책에서 확인할 수 있습니다, 콘솔 및 PC 게임 성능 최적화성능 최적화를 위한 80가지가 넘는 실행 가능한 팁과 모범 사례로 가득합니다.

캔버스 분할

문제 UI 캔버스에서 단일 요소가 변경되면 캔버스 전체가 더럽혀집니다.

캔버스는 Unity UI의 기본 구성 요소입니다. 그 위에 배치된 UI 요소를 나타내는 메시를 생성하고, UI 요소가 변경되면 메시를 재생성하며, 실제로 UI가 표시되도록 GPU에 드로 콜을 발행합니다.

이러한 메시를 생성하는 데는 비용이 많이 들 수 있습니다. UI 요소는 가능한 한 적은 수의 그리기 호출로 그려질 수 있도록 일괄적으로 수집해야 합니다. 일괄 생성은 비용이 많이 들기 때문에 필요할 때만 재생성하려고 합니다. 문제는 캔버스에서 하나 이상의 요소가 변경되면 해당 요소를 최적으로 그리는 방법을 파악하기 위해 전체 캔버스를 다시 한 번 분석해야 한다는 것입니다.

많은 사용자가 수천 개의 요소가 포함된 단일 캔버스에서 전체 게임 UI를 구축합니다. 한 가지 요소를 변경하면 수 밀리초 동안 CPU가 급증할 수 있습니다. 재구축 비용이 비싼 이유에 대해 자세히 알아보려면 이 유나이트 세션의 24:55분을 시청하세요.

솔루션: 캔버스를 분할합니다.

각 캔버스는 다른 캔버스의 요소와 분리된 섬입니다. 캔버스를 분할하여 여러 개의 캔버스를 지원하는 UGUI의 기능을 활용하여 Unity UI의 일괄 처리 문제를 해결하세요.

또한 캔버스를 중첩할 수 있으므로 디자이너는 캔버스에서 서로 다른 요소가 화면에 표시되는 위치를 고려할 필요 없이 큰 계층적 UI를 만들 수 있습니다. 자식 캔버스도 부모 캔버스와 형제 캔버스 모두에서 콘텐츠를 격리합니다. 자체 지오메트리를 유지하고 자체 일괄 처리를 수행합니다. 분할 방법을 결정하는 한 가지 방법은 얼마나 자주 새로 고쳐야 하는지에 따라 결정할 수 있습니다. 정적 UI 요소는 별도의 캔버스에, 동적 요소는 작은 하위 캔버스에 동시에 업데이트하는 방식으로 유지하세요. 또한 각 캔버스의 모든 UI 요소에 동일한 Z 값, 재질 및 텍스처가 있는지 확인합니다.

Graphic Raycaster 인터페이스
그래픽 레이캐스터 제한 및 레이캐스트 타깃 비활성화

문제 그래픽 레이캐스터의 부적절한 사용

그래픽 레이캐스터는 사용자의 입력을 UI 이벤트로 변환하는 컴포넌트입니다. 보다 구체적으로, 화면 클릭 또는 화면 터치 입력을 UI 이벤트로 변환한 다음 관심 있는 UI 요소로 전송합니다. 하위 캔버스를 포함하여 입력이 필요한 모든 캔버스에는 그래픽 레이캐스터가 필요합니다. 하지만 화면의 모든 입력 지점을 반복해서 살펴보고 해당 입력 지점이 UI의 렉트 트랜스폼 내에 있는지 확인하므로 잠재적인 오버헤드가 발생할 수 있습니다.

그래픽 레이캐스터는 이름과는 달리 실제로는 레이캐스터가 아닙니다. 기본적으로 UI 그래픽만 테스트합니다. 주어진 캔버스에서 입력을 받고자 하는 UI 요소 집합을 가져와 교집합 검사를 수행합니다. 예를 들어, 그래픽 레이캐스터의 캔버스에서 각 UI 요소의 렉트 트랜스폼에 대해 입력 이벤트가 발생하는 지점이 인터랙티브한 것으로 표시되어 있는지 확인합니다.

문제는 모든 UI 요소가 업데이트를 수신하는 데 관심이 있는 것은 아니라는 점입니다.

솔루션: 비대화형 UI 캔버스에서 그래픽 레이캐스터를 제거하고 정적 또는 비대화형 요소에 대한 레이캐스트 타깃을 끕니다.

특히 레이캐스트 타겟을 끄는 버튼의 텍스트는 그래픽 레이캐스터가 각 프레임에서 수행해야 하는 교차점 확인 횟수를 직접적으로 줄여줍니다.

문제 가끔 그래픽 레이캐스터가 레이캐스터 역할을 하기도 합니다.

캔버스에서 렌더 모드를 월드스페이스 카메라 또는 스크린 스페이스 카메라로 설정한 경우 차단 마스크를 추가할 수 있습니다. 차단 마스크는 레이캐스터가 2D 또는 3D 피직스를 통해 광선을 투사할지 여부를 결정하여 어떤 피직스 오브젝트가 사용자의 UI 상호작용을 차단하고 있는지 여부를 판단합니다.

솔루션: 2D 또는 3D 피직스를 통해 광선을 캐스팅하는 데는 비용이 많이 들 수 있으므로 이 기능을 아껴서 사용하세요.

이 경우 인터랙션 이벤트를 확인할 이유가 없으므로 그래픽 레이캐스터를 비대화형 UI 캔버스에서 제외하여 그래픽 레이캐스터의 수를 최소화합니다.

이 문서에서 그래픽 레이캐스터에 대해 자세히 알아보세요.

그리드 인터페이스
값비싼 UI 요소 피하기

문제 큰 목록, 그리드 보기 및 수많은 겹쳐진 UI 요소는 비용이 많이 듭니다.

큰 목록 및 그리드 보기는 비용이 많이 들고, 수많은 UI 요소(예: 카드 배틀 게임에서 쌓인 카드)를 겹쳐서 표시하면 오버드로가 발생합니다.

솔루션: 겹쳐진 UI 요소가 많지 않도록 하세요.

런타임에 계층화된 UI 요소를 더 적은 수의 요소와 배치로 병합하도록 코드를 사용자 지정하세요.

수백 개의 항목이 있는 인벤토리 화면과 같이 큰 목록 또는 그리드 보기를 만들어야 하는 경우 각 항목에 대해 단일 UI 요소 대신 더 작은 UI 요소 풀을 재사용하는 것이 좋습니다.

최적화된 스크롤 목록의 예는 이 GitHub 프로젝트를 확인하세요.

레이아웃 그룹 인터페이스
가능하면 레이아웃 그룹을 피하십시오.

문제 레이아웃을 더럽히려고 하는 모든 UI 요소는 적어도 한 번 이상의 GetComponent 호출을 수행합니다.

레이아웃 시스템에서 하나 이상의 하위 UI 요소가 변경되면 레이아웃이 "더럽혀집니다." 변경된 하위 요소는 해당 요소를 소유한 레이아웃 시스템을 무효화합니다.

레이아웃 시스템은 레이아웃 요소 바로 위에 있는 연속적인 레이아웃 그룹의 집합입니다. 레이아웃 요소는 레이아웃 요소 구성 요소(UI 이미지, 텍스트, 스크롤 레코드)뿐만 아니라 스크롤 레코드도 레이아웃 그룹인 것처럼 레이아웃 요소로 구성됩니다.

이제 당면한 문제에 대해 말씀드리겠습니다: 레이아웃을 "더티"로 표시하는 모든 UI 요소는 최소한 한 번 이상의 GetComponent 호출을 수행합니다. 이 호출은 레이아웃 요소의 부모에서 유효한 레이아웃 그룹을 찾습니다. 레이아웃 그룹을 찾으면 레이아웃 그룹 찾기를 중단하거나 계층 구조 루트에 도달할 때까지(둘 중 먼저 도달하는 쪽) 계속해서 트랜스폼 계층 구조를 따라 올라갑니다. 따라서 각 레이아웃 그룹은 각 하위 레이아웃 요소의 더티 프로세스에 GetComponent 호출을 하나씩 추가하므로 중첩된 레이아웃 그룹은 성능에 매우 좋지 않습니다.

솔루션: 레이아웃 그룹은 가급적 피하세요.

비례 레이아웃에는 앵커를 사용합니다. UI 요소 수가 동적으로 많은 핫 UI에서는 레이아웃을 계산하는 코드를 직접 작성하는 것이 좋습니다. 매번 변경할 때마다 사용하는 것이 아니라 필요할 때마다 사용하세요.

문서에서 레이아웃 그룹에 대해 자세히 알아보세요.

오브젝트 풀링 인터페이스
스마트한 방식으로 UI 개체 풀링

문제 잘못된 방식으로 UI 객체 풀링

사람들은 종종 UI 오브젝트를 다시 부모로 설정했다가 비활성화하여 풀링하는데, 이는 불필요한 더티를 유발합니다.

솔루션: 먼저 개체를 비활성화한 다음 풀에 다시 부모로 설정합니다.

이전 계층 구조를 한 번 더럽힐 수는 있지만, 다시 부모가 되면 이전 계층 구조를 두 번 더 더럽히지 않고 새 계층 구조를 전혀 더럽히지 않게 됩니다. 풀에서 개체를 제거하는 경우 먼저 개체를 다시 부모로 지정하고 데이터를 업데이트한 다음 활성화하세요.

Unity의 기본 오브젝트 풀링의 개념에 대해 자세히 알아보세요.

UI Canvas 컴포넌트
캔버스를 숨기는 방법

문제 캔버스를 숨기는 방법을 잘 모르겠습니다.

때때로 UI 요소와 캔버스를 숨기는 것이 유용할 때가 있습니다. 하지만 이를 효율적으로 수행하려면 어떻게 해야 할까요?

솔루션: 캔버스 컴포넌트 자체를 비활성화합니다.

캔버스 컴포넌트를 비활성화하면 캔버스가 GPU에 그리기 호출을 실행하지 않습니다. 이렇게 하면 캔버스가 더 이상 표시되지 않습니다. 그러나 캔버스는 버텍스 버퍼를 버리지 않고 모든 메시와 버텍스를 유지합니다. 그런 다음 다시 활성화하면 다시 빌드를 트리거하지 않고 다시 그리기만 시작합니다.

또한 캔버스 컴포넌트를 비활성화해도 캔버스 계층구조를 통해 값비싼 OnDisable/OnEnable 콜백이 트리거되지 않습니다. 다만 프레임당 비용이 많이 드는 코드를 실행하는 하위 컴포넌트는 비활성화하도록 주의하세요.

여기에서 캔버스 컴포넌트에 대해 자세히 알아보세요.

UI 요소에서 최적의 애니메이터 사용

문제 UI에서 애니메이터 사용

애니메이터는 애니메이션의 값이 변경되지 않더라도 매 프레임마다 UI 엘리먼트를 더티 처리합니다.

솔루션: UI 애니메이션에 코드를 사용합니다.

항상 변경되는 동적 UI 요소에만 애니메이터를 배치합니다. 거의 변경되지 않거나 이벤트에 따라 일시적으로 변경되는 요소의 경우 직접 코드를 작성하거나 트위닝 시스템을 사용하세요. 에셋 스토어에는 이를 위한 여러 가지 훌륭한 솔루션이 있습니다.

전체 화면 UI를 사용할 때는 다른 모든 항목을 숨깁니다.

문제 전체 화면 UI의 성능 저하

게임에서 장면을 완전히 덮는 일시 중지 또는 시작 화면이 표시되는 경우 게임의 나머지 부분은 여전히 백그라운드에서 렌더링되고 있으므로 성능에 영향을 줄 수 있습니다.

솔루션: 다른 모든 것을 숨깁니다.

씬의 다른 모든 것을 가리는 화면이 있는 경우 3D 씬을 렌더링하는 카메라를 비활성화합니다. 마찬가지로 상단 캔버스 뒤에 숨겨진 캔버스 요소를 비활성화합니다.

전체 화면 UI에서는 60fps로 업데이트할 필요가 없으므로 Application.targetFrameRate를 낮추는 것을 고려하세요.

리소스 더 보기
게임 성능 최적화
자세한 내용은 무료 전자책 받기

플레이어에게 최고의 게임 경험을 제공하세요. 유니티의 전문 엔지니어가 제공하는 80개 이상의 실행 가능한 팁과 베스트 프랙티스를 통해 PC 및 콘솔 게임을 최적화할 수 있습니다.

특히 유니티의 성공 및 가속화 솔루션 엔지니어링 팀이 최고의 스튜디오와의 실제 작업에서 수집한 세부 사례를 통해 게임의 전반적인 성능을 향상하는 데 도움이 될 것입니다.

이 콘텐츠가 도움이 되었나요?