리얼타임 시뮬레이션 및 게임, 렌더링, 게임플레이에는 유저 인터페이스(UI)에 비해 훨씬 많은 CPU, GPU, 텍스처 메모리가 필요합니다. 그러므로 UI는 대개 다른 시스템에 비해 적은 퍼포먼스 예산을 할당받으며, 리소스가 적은 디바이스에서는 이 예산 제약이 특히 자주 체감됩니다. 따라서 리소스를 최대한 효율적으로 사용하고 가능한 한 UI에서의 리소스 소비를 줄이는 것이 중요합니다.
UI에 필요한 리소스는 프로젝트와 타깃 플랫폼의 디테일에 따라 달라지지만, 언리얼 엔진 에서 슬레이트(Slate) 및 UMG 로 UI를 제작할 때 따를 수 있는 최적화 가이드라인이 있습니다. 이 페이지에서는 다음 내용을 포함하여 이러한 모범 사례에 대한 개요를 제공합니다.
- 퍼포먼스 풋프린트를 줄일 수 있는 최적화 기능.
- CPU에 큰 부담을 주는 위젯에 대한 가이드라인.
- UMG 레이아웃 제작 시 피해야 할 것들에 대한 정보.
- UMG 내 여러 애니메이션 메서드의 CPU 비용 개요.
최적화 및 프로파일링에 대한 일반 정보는 다음 페이지를 참조하세요.
인밸리데이션
인밸리데이션(Invalidation) 은 슬레이트 위젯의 정보를 캐싱한 다음, 여기서 페인팅, 레이아웃, 계층구조 정보를 무효화하는 변경 사항을 모니터링합니다. 위젯이 변경되지 않는 한, 슬레이트는 위젯을 다시 페인팅하지 않고 캐싱된 정보로 예비 전환합니다. 변경 사항이 이 정보를 무효화하면, 슬레이트는 정보를 재계산하고 위젯을 다시 페인팅합니다.
언리얼 엔진은 UI에 인밸리테이션을 통합하는 몇 가지 방법을 다음과 같이 제공합니다.
- 인밸리데이션 박스(Invalidation Box)는 자손 위젯의 정보를 캐싱합니다.
- 글로벌 인밸리데이션(Global Invalidation)은 전체
SWindow
를 인밸리데이션 박스로 취급하고 전체 UI에 인밸리데이션을 적용합니다. - 리테이너 패널(Retainer Panel)은 자손 위젯을 페인팅하기 전에 단일 텍스처로 플래튼하고 프레임 레이트를 환경설정하거나 렌더링을 지연하는 옵션을 제공합니다.
인밸리데이션은 자주 변경되지 않는 위젯 그룹에 가장 효과적이며, 메모리를 소모하는 대신 CPU 로드가 각 프레임을 다시 페인팅하는 데 소모되지 않게 합니다. 프레임 단위로 변경되는 위젯은 프레임마다 다시 페인팅되므로, 불필요하게 정보를 캐싱하지 않도록 휘발성(Volatile) 이라고 표시해야 합니다.
이 시스템에 대한 추가 정보와 상세한 구현 방법 및 한계에 대해서는 슬레이트 및 UMG의 인밸리데이션을 참조하세요.
프로그래밍 및 스크립팅
다음은 UMG 환경에서의 프로그래밍을 위한 모범 사례입니다.
틱 시 또는 페인팅 시 로직 사용 최소화
가능한 한 UI 로직 실행에는 틱 시(On Tick) 또는 페인팅 시(On Paint)를 사용하지 않아야 합니다. 이벤트 디스패처와 델리게이트를 활용하면 틱에 의존하지 않고도 특정 이벤트에 반응하는 로직을 만들 수 있습니다.
바운드 어트리뷰트 대신 이벤트 기반 업데이트 사용
UI에서 어트리뷰트를 필드에 바인딩하면 어트리뷰트가 프레임마다 할당됩니다. 예를 들어 텍스트 필드의 텍스트 값을 integer에 바인딩하면, 진행률 표시줄이 integer 값을 틱마다 해당 필드에 할당할 것입니다. 이러면 비효율적이므로 바운드 어트리뷰트의 사용은 삼가야 합니다.

원시 어트리뷰트 바인딩은 절대 사용하지 마세요.
그 대신 프로젝트가 UI의 함수 및 이벤트를 호출하여 이러한 필드를 업데이트하도록 구성해야 합니다. 예를 들어 체력 표시줄을 Health 어트리뷰트에 바인딩하기보다는, UI의 블루프린트 스크립트에서 OnHealthChanged
이벤트를 호출하여 UI의 필수 필드를 변경해야 합니다.

이벤트로 UI를 업데이트하는 예시입니다.
구성하는 데는 시간이 더 걸리지만, 이렇게 하면 UI가 매 프레임 변경되지 않고 값이 바뀌는 프레임에만 변경됩니다.
로딩 및 생성
다음은 위젯을 구조화하고 런타임에 구축하기 위한 모범 사례입니다.
사용되지 않는 위젯 최소화
위젯 내의 모든 자손은 표시 여부와 관계없이 로드 및 생성됩니다. UI가 렌더링하지 않더라도 메모리를 사용하며, 로딩 및 생성 시간을 필요로 합니다.
기초 수준에서 UI 디자이너는 사용되지 않는 위젯을 정기적으로 확인하고 작업을 커밋하기 전에 제거해야 합니다. 정기적인 수정 작업은 조직화와 퍼포먼스에 도움이 됩니다.
복잡한 위젯을 런타임에 로드할 수 있는 조각으로 분해
주요 시스템을 위한 특별히 복잡한 위젯에는 전체 기능을 처리하기 위해 자손이 1,000개를 훌쩍 넘는데, 그중 동시에 표시되는 것은 몇백 개뿐인 경우가 있습니다. 이런 상황에 전체 위젯을 한꺼번에 로드한다면 수백 개의 비활성 자손이 사용되지도 않으면서 자리를 차지할 것입니다. 이들 자손 위젯의 세분화 정도에 따라서는 사용자가 수백 개의 위젯을 몇 시간 동안 보지 않을 수도 있습니다.
이런 경우, 위젯을 카테고리로 나눠야 합니다.
-
항상 표시되는 위젯
-
가능한 한 빨리 표시되어야 하는 위젯
-
약간의 표시 지연시간이 있어도 괜찮은 위젯
빠른 응답 시간을 필요로 하는 위젯은 표시되지 않을 때도 백그라운드에 로드되어야 합니다. 예를 들어 경쟁형 슈팅 게임의 인벤토리 화면은 플레이어에게 핵심적인 기능이기 때문에 자주 사용되며 반응성이 높아야 합니다. 따라서 로드해 두고 표시되지 않게 하는 것이 좋습니다.
오랫동안 표시되지 않고 빠른 반응이 필요하지도 않은 위젯은 런타임에 비동기로 로드되고 닫으면 소멸되게 해야 합니다. 다양한 기능이 있는 복잡한 위젯의 경우, 베이스 위젯은 항상 로드된 채로 유지하고 어떤 모드나 기능이 필요한지에 따라 여러 자손 위젯 세트를 비동기로 로드해야 합니다. 이렇게 하면 메모리를 크게 절약하고 초기화 시의 CPU 영향을 줄일 수 있습니다.
레이아웃 및 위치 지정
다음은 UI의 레이아웃을 만들 때 위젯의 효율을 향상하기 위한 가이드라인입니다.
캔버스 패널 사용 최소화
캔버스 패널(Canvas Panel) 은 좌표 평면과 위젯별 앵커를 사용하여 다른 위젯의 위치를 정할 수 있는 강력한 컨테이너 위젯입니다. 이를 사용하면 위젯을 정확히 원하는 곳에 배치하면서 위젯의 위치를 화면 구석, 모서리, 중앙에 상대적으로 유지할 수 있습니다.
그러나 캔버스 패널은 높은 퍼포먼스를 필요로 합니다. 슬레이트의 드로 콜은 위젯의 레이어 ID별로 그룹화됩니다. 가로 박스나 세로 박스 등 다른 컨테이너 위젯은 자손 위젯의 레이어 ID를 통합하므로 드로 콜의 수를 줄입니다. 그러나 캔버스 패널은 자손 위젯이 필요할 때 다른 위젯 위에 렌더링될 수 있도록 ID를 늘립니다. 그러므로 캔버스 패널은 다수의 드로 콜을 사용하며, 다른 수단에 비해 훨씬 CPU 집약적입니다.
오버레이 패널 또한 레이어 ID를 추가하므로 다수의 드로 콜을 사용합니다. 캔버스 패널보다는 제한된 범위로 사용되기 때문에 영향도 적지만, 그래도 오버레이 패널을 사용할 때는 이 점에 유의해야 합니다.
캔버스 패널 하나를 사용하여 HUD나 메뉴 시스템을 위한 루트 위젯을 배치하는 것은 문제가 되지 않습니다. 상세한 위치 지정이나 복잡한 Z 정렬이 필요할 가능성이 높기 때문입니다. 그러나 텍스트 박스, 커스텀 버튼, 기타 템플릿 엘리먼트 등 개별 커스텀 위젯을 캔버스 패널로 배치하는 것은 피해야 합니다. 그랬다간 UI의 여러 엘리먼트에서 캔버스 패널을 여러 레이어로 중첩하게 되어 리소스 소모가 대단히 심해집니다. 또한 캔버스 패널을 다수의 레이어에서 과도하게 사용하면, UI의 어떤 레이어가 최종 레이아웃을 결정하는 부분인지 분간하기가 어려워질 수 있습니다.
위젯이 단일 엘리먼트로 구성된 경우에는 캔버스 패널이 전혀 필요하지 않습니다. 전체 메뉴와 HUD에서도 오버레이(Overlay) 및 사이즈 박스(Size Box) 를 가로(Horizontal) , 세로(Vertical) , 그리드 박스(Grid Box) 와 함께 사용하여 레이아웃을 처리하면 캔버스 패널을 사용하는 것은 피할 수 있습니다.
가능한 경우 사이즈 박스 대신 스페이서 사용
사이즈 박스는 크기를 계산하고 자체를 렌더링하기 위해 다수의 패스를 사용합니다. 너비와 높이가 특정 크기를 차지하는 콘텐츠가 필요한 경우 스페이서(Spacer) 의 비용이 훨씬 낮습니다.
스케일 박스와 사이즈 박스 결합 피하기
스케일 박스(Scale Box) 를 사이즈 박스와 결합하면, 두 박스가 서로를 업데이트하려고 시도하면서 프레임마다 두 사이즈를 오가는 루프에 빠질 것입니다. 둘 중 하나에 의존하지 말고 레이아웃이 콘텐츠의 기본 크기에 따라 작동하도록 만들어야 합니다.
리치 텍스트 위젯 사용 최소화
리치 텍스트 위젯(Rich Text widget) 은 텍스트에 강력한 포맷 지정 기능을 제공하지만, 추가 기능을 더할 수 있기 때문에 표준 텍스트 박스보다 훨씬 비용이 높습니다. 텍스트에 스타일을 적용하거나 표현력을 강화하고 싶지만 리치 텍스트의 기능 전체가 필요하지는 않다면, 원하는 스타일의 느낌을 기본적으로 반영하는 폰트를 선택 또는 제작하고 표준 텍스트 위젯으로 예비 전환하는 것이 좋습니다.
애니메이션 비용
런타임에 위젯을 애니메이팅하는 방법에는 여러 가지가 있습니다. 인밸리데이션으로 작업하는 경우, 이러한 방법 중 일부는 위젯 레이아웃을 무효화하여 계층구조의 전체 브랜치가 다시 업데이트되게 할 수 있습니다. 다음 표는 UMG의 애니메이션 방법들과 그 상대적 CPU 비용입니다.
비용 | 예시 |
---|---|
CPU 비용 없음/가장 낮음 | 머티리얼만 있는 애니메이션. |
CPU 비용 낮음 | 블루프린트로 스크립팅되고 시퀀서를 필요로 하지 않는 애니메이션. |
CPU 비용 높음 | UMG의 애니메이션 에디터로 만들어진 시퀀서 애니메이션. |
CPU 비용 가장 높음 | 레이아웃 변경을 유발하는 애니메이션. |
머티리얼만 있는 애니메이션은 GPU로 처리되므로 CPU 비용을 유발하지 않습니다. 발광 이펙트, 백그라운드 스크롤링, 기타 머티리얼 변경으로 표현될 수 있는 이펙트 등의 루핑 애니메이션에 적합합니다. 애니메이션을 머티리얼에 포함할 수 있다면, 이 방법을 가장 우선해야 합니다.
UMG의 애니메이션 에디터는 시퀀서 구현입니다. 색과 같이 트랜스폼이 아닌 어트리뷰트를 변경하는 시퀀서 애니메이션은 위젯을 다시 그리게 하지만 레이아웃을 무효화하지는 않습니다. 렌더 트랜스폼의 변경을 유발하는 애니메이션은 레이아웃 인밸리데이션을 유발하며, 이에 따라 애니메이션이 위젯을 변경하는 매 프레임마다 레이아웃을 재계산합니다. 이런 애니메이션을 피하거나, 이런 애니메이션이 필요한 위젯을 휘발성으로 표시해야 합니다.
블루프린트 스크립팅된 애니메이션과 시퀀서 애니메이션의 실행 비용은 거의 같지만, 시퀀서 애니메이션은 애니메이팅을 시작하기 전에 애니메이션 오브젝트를 초기화하고 애니메이션이 담당하는 프로퍼티 경로를 해석해야 합니다. 즉, 블루프린트 스크립팅 애니메이션에는 없는 스타트업 비용이 시퀀서 애니메이션에는 있습니다. 그러므로 대미지 수치 애니메이션처럼 짧고 자주 사용되는 애니메이션을 작업하는 경우, 시퀀서를 피하고 블루프린트 스크립팅 방식을 사용해야 합니다.