Unity UI 시스템 최적화(UGUI)
* 본 콘텐츠는 오버레이 UI를 중심으로 제작되었으며, 월드 캔버스는 다를 수 있습니다.
UGUI의 병목 현상 원인
GPU 바운드
Unity는 그래픽으로 렌더링하기 때문에 GPU를 사용하고 GPU 병목 현상을 일으킬 수 있습니다.
1. 필레이트 병목 현상
– 고해상도, 중첩 드로잉, 오버 드로잉, 무거운 픽셀 셰이더(Unity Shader 제한으로 인해 낮은 확률) 등
* 필레이트: GPU가 화면에 렌더링할 수 있는 초당 픽셀 수입니다.
CPU 바운드
대부분의 경우 CPU가 병목 현상입니다.
1. 드로우 콜/배치
2. 캔버스 스택 구성을 위한 계산 시간
– 각 프레임에서 동적 UI를 재구축하기 위한 계산 시간
3. 정점 생성 시간
– GPU가 렌더링하기 때문에 UI에도 정점이 필요하므로 정점을 생성하는 데 시간이 걸립니다.
4. 다양한 UI 요소 등
UI 메시
와이어프레임 뷰를 확인해보면 UI도 메쉬로 되어 있음을 알 수 있습니다.
따라서 3D 그래픽에서 고려해야 하는 동일한 병목 현상을 사용자 인터페이스에서도 고려해야 합니다.
메쉬는 어떻게 만들어지는가
1. 다각형은 정점 정보(정점 버퍼)와 정점을 그리는 순서를 포함하는 정보(인덱스 버퍼)로 구성됩니다.
2. 렌더링 상태에서 다각형을 시계 반대 방향으로 그릴지 시계 방향으로 그릴지 선택합니다.
3. 렌더링 상태에서 다각형을 삼각형으로 그릴지 여부를 지정합니다(삼각형 목록).
* CCW, CW 상관없이 뒷면을 제거하지 않고 양면을 그리는 설정이 있습니다.
4. 정점(Vertex Decl)을 정의합니다. 정점 버퍼는 GPU가 데이터(위치, 색상, UV 좌표)를 분할하여 읽는 방법을 정의하는 데이터 공간입니다.
* UV Coordinates: 3D 공간에서 폴리곤에 텍스처를 적용하기 위한 기준이 되는 2D 좌표계
렌더링 정보는 CPU 메모리에 계산 데이터 형태로 생성되어 GPU 메모리로 전달됩니다.
정적 3D 객체의 경우 로드 시 한 번 계산되어 GPU 메모리로 전송되고 저장된 데이터를 기반으로 렌더링됩니다.
메쉬가 변경되는 UI와 같은 동적 객체의 경우 CPU가 각 프레임을 계산하여 GPU로 전송해야 하므로 계산 비용이 발생합니다.
이 때문에 UI의 CPU 측에 많은 병목 현상이 있습니다.
그래픽(.cs)
그래픽 요소를 포함하는 클래스
그래픽은 Unity UI C# 라이브러리에서 제공하는 기본 클래스입니다.
Unity의 이미지, 텍스트 및 TMP_Text 클래스는 그래픽 클래스물려받다
재건 ()
동적 개체 정점 변경(UpdateGeometry) 및 재질 변경(UpdateMaterial)이 이루어진 것을 볼 수 있습니다.
DoMeshGeneration()
OnPopulateMesh() : 새로운 정점 버퍼(AddVert) 및 인덱스 버퍼(AddTriangle) 설정
FillMesh(): 지정된 데이터(정점, 색상, UV, 법선, 접선, 삼각형)를 메쉬에 추가하는 프로세스
캔버스(.cpp)
실제 렌더링 클래스로 메쉬 구성GPU에 알리십시오 풀 콜하다
각 캔버스에서 일괄 처리가 발생하기 때문에 캔버스의 하위 개체가 수정될 때마다 캔버스가 다시 생성됩니다.
Canvas 클래스는 RenderOverlays()를 상속하고 RenderOverlays를 재귀적으로 호출합니다.
다시 말해서 캔버스당 렌더링이렇게 되어 있는 것을 볼 수 있으며, 자식 캔버스가 있으면 자체적으로 데이터를 관리하게 됩니다.
그러므로 정적 UI와 동적 UI를 분리하여 캔버스 구성이렇게 하는 것이 좋지만 다음과 같은 상황에 따라 선택이 달라질 수 있습니다. B. 연장 비용 및 주문형 통화 비용.
중첩된 캔버스
캔버스는 캔버스를 소유할 수 있습니다.
캔버스에는 중첩된 캔버스 목록이 있으며 RenderOverlays()를 호출합니다.
루트 캔버스에서 관리하는 것이 가장 좋습니다. 편리한 관리를 위한 중첩 캔버스 기법사용할 수 있습니다
재구성은 하위 캔버스 간에 영향을 미치지 않습니다(상위 캔버스의 크기가 조정되는 경우 제외).
더러운 깃발
불필요한 계산을 최소화하기 위해 더티라는 플래그를 변경된 값으로 설정하고 즉시 계산을 수행합니다.
값이 소비되는 것보다 더 많이 계산될 때(예: 계층 구조의 개체) 사용되는 대로 변경하고 계산하는 값에 플래그를 지정하는 방법입니다.
* 더티 플래그 디자인 패턴: https://mm5-gnap.353
문제는 UI가 지속적으로 업데이트되고 있다는 것입니다. 더티 플래그 스타일로 구현됨되었습니다
직사각형 변환(.cpp)
Transform을 상속하기 때문에 계층 구조로 구성되어 있으며 개체 변경 사항은 계층적으로 영향을 미칩니다. (= 계층 구조가 깊을수록 계산 노력이 더 많이 듭니다.)
부모 재지정 비용: 계층 구조에서 부모가 변경되면 구조의 데이터를 변경해야 하므로 비용이 발생합니다.
(Transformation은 계층적 구조로 이루어져 있으며, 멀티스레드 멀티스레딩을 사용하여 연산을 메모리에 지속적으로 저장한다. 리매핑이 발생하면 메모리를 재정렬하므로 비용이 많이 들 수 있다.)
*재매핑은 개체를 풀링할 때 때때로 수행되지만 비용이 발생한다는 점을 기억하십시오.
재건
C# 그래픽 구성 요소의 레이아웃 및 메시 재계산
– 더러운 구성 요소/개체를 기반으로 한 재계산
변경 사항에 따라 비용이 달라질 수 있습니다.
1) UI 요소 레이아웃 변경 시 -> 더티 레이아웃
– 계층 구조의 깊이별로 정렬
2) UI 요소의 그래픽이 변경된 경우 -> Dirty Graphic
– Vertex Data Dirty(RectTransform 크기 조정): 메시 재구축
– Material Data Dirty (Texture Change) 연결된 캔버스 렌더러의 Material 업데이트
활성화된 모든 요소의 메쉬 재생성
– 완전히 투명한(alpha==0)도 생성됩니다. (예: 페이드 인/아웃)
배치 기반 재료 재생성
– 캔버스 기반으로 렌더링 되지만 쉐이더나 머티리얼에 따라 드로우 콜이 여러 번 나타날 수 있습니다.
(배치 팩터에 주의를 기울여야 합니다.)
프로파일러
아래 프로파일러로 확인하실 수 있습니다.
– CanvasUpdate.Prelayout, CanvasUpdate.Layout, CanvasUpdate.PostLayout
– CanvasUpdate.PreRender, CanvasUpdate.LatePreRender
– Canvas.SendWillRenderCanvases
(쓰기: 51:34부터 계속 배우세요)

