📌 3월 알쓸유잡: Unity UI 시스템 (UGUI)의 성능 최적화 📍 UGUI 시스템 구조 및 개념 파악하기 (feat. 유니티 소스 코드) 00:00 인트로 03:32 UGUI의 병목 (GPU, CPU 바운드 등) 09:03 메시로 구성된 UI 11:28 데이터의 조합, 메시 18:00 그래픽 요소를 담은 Graphic 클래스 23:57 렌더링이 이루어지는 Canvas (.cpp) 31:36 하위 캔버스 생성 및 별도 관리가 가능한 Nested Canvas 36:46 계층 구조 시스템에 활용하는 Dirty flag 40:01 Transform을 상속받는 RectTransform (.cpp) 45:15 레이아웃과 메시를 다시 계산하는 Rebuild 53:36 렌더링 명령을 위한 Batch building (Canvas) 56:14 Batching의 4가지 기준 57:12 Batching 데모로 확인하기 1:10:26 Transparent 오브젝트에 영향을 주는 Rendering order 1:12:51 투명 오브젝트에서의 Overdraw 이슈 1:13:31 UI에서의 Pixel Perfect 📍 UGUI 시스템 성능 최적화 TIP 1:21:41 UI 구조화에 유용한 Layout Components 1:26:38 Layout Components 활용 팁 1:27:55 Q. 레이아웃 컴포넌트를 런타임 상에서 비활성화하고 에디터 모드에서 작동하게 하는 옵션이 있나요? 1:30:06 권장사항: Object Pool 활용하기 1:32:35 항상 변경되는 동적인 UI에만 Animator 사용하기 1:35:39 필요한 곳에서만 Raycaster 사용하기 1:38:25 Full Screen UI 사용 시 3D 오브젝트 렌더링하지 않기 1:39:50 Text 대신 Icon 사용하기 1:41:02 글자를 미리 텍스처로 제작하는 Text Mesh Pro 1:46:04 Xcode & Instrument로 프로파일링하기 📍성능 최적화 관련 유용한 유니티 가이드 - 게임 개발을 최적화하는 9가지 방법: on.unity.com/3JjiMy5 - Optimize your game performance for Consoles and PC: on.unity.com/3LxNzKp - Ultimate guide to profiling Unity games: on.unity.com/3YRmu7R - 모바일 게임 성능 최적화 팁: on.unity.com/3TmyrRC
1. 32:46 캔버스 하나에 여러 UI를 한 번에 묶는 것보다, 자식 캔버스(Nested Canvas)를 두는 것을 권장. 이유는, 부모 Canvas에 수정 사항이 발생하지 않는 이상, 자식 Canvas의 UI가 Dirty 될 때 해당 Canvas만 갱신시킨다. 만약 한 캔버스 안에 모두 담아둔다면 자식 중 하나만 변경되어도 모든 자식들을 갱신하는 비용이 있다. 그렇다고 모든 자식들이 캔버스를 갖고있는 것은 비추천. 무거울수 있기 때문. UI 최적화는 케바케가 심하므로 완벽한 정답이 없으니 상황에 맞게 사용하길 권장 (etc: 동적인 객체, 정적인 객체 나눠서 등) 2. 43:30 uI 풀링할때 reparenting 하는 경우가 있는데 저렴한 비용이 아니다. 그 이유는 RectTransform이 계층 구조를 가진 Transform을 상속받고있고, 부모가 바뀌게 되면 본인 포함 자식 개체들을 갱신시켜준다. (OnBeforeTransformParentChanged, OnTransformParentChanged, OnTransformChildrenChanged) 3. 59:40 3D 같은 경우 Frame Debugger에서 충분히 Batching이 깨진 이유를 설명해주나, UI는 그 원인을 설명을 안해줌. 그러므로 UI는 프로파일러 내에 UI 항목을 확인하는 것이 편함. 어떤 UI를 그려주는 Batching인지 확인할뿐더러 배칭이 깨진 이유를 설명해줌 (ex. Use Different Texture) 4. 1:09:30 블렌딩이 들어가는 쉐이더는, 불투명 X 반투명O, Z값에 따라 나눠 그리기 때문에 (Back-To-Front) Z값을 나누게 될 경우 배칭이 깨지게 된다. 이는 UI에도 적용이 되므로 Z값을 나눠 작업하게되면 배칭이 깨지게 된다. (번외) 스프라이트 같은 경우 알파값이 0이어도 Active 상태면 렌더링, 더티 대상이다. 5. 1:11:30 Ui 스프라이트의, 특히 동적인 애들, Pixel Perfect는 성능에 많은 악영향을 끼친다. RectTransform 변경 시 모든 정점을 재계산하기 때문이다. 6. 1:16:12 그럼에도 Pixel Perfect를 놓치고 싶지 얂으면, 따로 스크롤링 할 때만 꺼주는 기능을 넣거나 그 외 별도 작업 (ex. Nested Canvas들 중 픽셀퍼펙트가 필요없는 것들은 Off로 설정) 을 해줘야 한다. 7. 1:26:02 Layout 정렬 관련 컴포넌트 (Layout Group, Grid, 등등)은 초기 세팅 시 혹은 요소의 특성(행렬이 적용되는 T•R•S 등) 변경 시에만 Enable해주고 필요없을 땐 Disable을 해주는 것이 좋다. 8. 1:27:00 버튼 같은 경우 여러 가지의 상태 혹은 테두리를 나타내기 위해 각각의 오브젝트를 두지 말고 성능을 위해, 추가작업이 필요하지만, 하나의 버튼 안에서 다 처리해줘야한다. 예를 들어 같은 크기의 Sprite만 변경해줬을 때는 Dirty가 발생하지 않기 때문에 (이건 앞에서 설명해주심) 성능 측면에서 효율적이다. 9. 1:29:40 UI도 스크롤 같이 같은 타입의 개체를 많이 사용해야하는 경우 오브젝트 풀링을 사용하길 권장. (Optimized, Unoptimized 비교하는 모습 보여주시고있음) 10. 1:30:40 버튼 움직임이라든지 화려한 연출을 위해 보통 애니메이터를 사용하는데 애니메이터는 KeyFrame 방식으로 동작하므로, Idle 상태일 때도 Dirty가 발생하니깐 항상 변경되는 UI [Idle일 때도 움직이는]에만 애니메이터를 적용하는 것을 권장한다. 대신에 코드로 된 외부 플러그인 (DoTween)을 사용하거나 직접 코드를 작성해서 애니메이팅 하는 것을 권장한다. 11. 1:34:17 불필요한 이미지의 Raycast Target을 비활성화하고 필요한 곳에서만 Raycaster를 사용 12. 1:36:20 화면 전체를 덮는 UI를 활성화 했으며 뒤에 3d배경이 켜져있을 필요가 없다면 해당 장면을 렌더링하는 카메라를 꺼주거나 빈 곳을 보도록 돌려버려야한다. 하지만, 카메라를 껏다켰다하면 오버헤드가 발생할 수 있으니 다른 곳을 보도록 하는 것이 더 효율적일 수 있다. 13. 1:37:20 전체 화면을 덮는 UI가 활성화되었을 때, UI는 60프레임까지 돌릴 필요없으니, 모바일 기준으로 배터리 및 자원을 아끼기 위해 풀스크린UI 상태에서는 타겟 프레임 레이트를 30으로 낮춘다거나 비슷한 작업을 해주길 권장.
1:24:55 에서 '재구성이 필요할 때 레이아웃을 활성화' 이 부분에서 좀 궁금한 게 있는데 레이아웃을 활성화 한 상태에서 가만히 두어도 SetDirty()가 발생하나요? 테스트 해보니 레이아웃 그룹의 자식을 건들지 않는 이상 SetDirty()가 실행되진 않는 것 같은데 그러면 굳이 레이아웃을 비활성화, 활성화 할 필요 없이 레이아웃을 활성화 한 상태로 두어도 성능 측면에서 이슈가 없지 않나요? 꼭 재구성이 필요할 때 다시 켰다가 끄는 것이 성능에 좋습니까? 그렇다면 정량적으로 얼마만큼 좋습니까?
📌 3월 알쓸유잡: Unity UI 시스템 (UGUI)의 성능 최적화
📍 UGUI 시스템 구조 및 개념 파악하기 (feat. 유니티 소스 코드)
00:00 인트로
03:32 UGUI의 병목 (GPU, CPU 바운드 등)
09:03 메시로 구성된 UI
11:28 데이터의 조합, 메시
18:00 그래픽 요소를 담은 Graphic 클래스
23:57 렌더링이 이루어지는 Canvas (.cpp)
31:36 하위 캔버스 생성 및 별도 관리가 가능한 Nested Canvas
36:46 계층 구조 시스템에 활용하는 Dirty flag
40:01 Transform을 상속받는 RectTransform (.cpp)
45:15 레이아웃과 메시를 다시 계산하는 Rebuild
53:36 렌더링 명령을 위한 Batch building (Canvas)
56:14 Batching의 4가지 기준
57:12 Batching 데모로 확인하기
1:10:26 Transparent 오브젝트에 영향을 주는 Rendering order
1:12:51 투명 오브젝트에서의 Overdraw 이슈
1:13:31 UI에서의 Pixel Perfect
📍 UGUI 시스템 성능 최적화 TIP
1:21:41 UI 구조화에 유용한 Layout Components
1:26:38 Layout Components 활용 팁
1:27:55 Q. 레이아웃 컴포넌트를 런타임 상에서 비활성화하고 에디터 모드에서 작동하게 하는 옵션이 있나요?
1:30:06 권장사항: Object Pool 활용하기
1:32:35 항상 변경되는 동적인 UI에만 Animator 사용하기
1:35:39 필요한 곳에서만 Raycaster 사용하기
1:38:25 Full Screen UI 사용 시 3D 오브젝트 렌더링하지 않기
1:39:50 Text 대신 Icon 사용하기
1:41:02 글자를 미리 텍스처로 제작하는 Text Mesh Pro
1:46:04 Xcode & Instrument로 프로파일링하기
📍성능 최적화 관련 유용한 유니티 가이드
- 게임 개발을 최적화하는 9가지 방법: on.unity.com/3JjiMy5
- Optimize your game performance for Consoles and PC: on.unity.com/3LxNzKp
- Ultimate guide to profiling Unity games: on.unity.com/3YRmu7R
- 모바일 게임 성능 최적화 팁: on.unity.com/3TmyrRC
유용한 내용 잘 배워갑니다~
1. 32:46 캔버스 하나에 여러 UI를 한 번에 묶는 것보다, 자식 캔버스(Nested Canvas)를 두는 것을 권장. 이유는, 부모 Canvas에 수정 사항이 발생하지 않는 이상, 자식 Canvas의 UI가 Dirty 될 때 해당 Canvas만 갱신시킨다. 만약 한 캔버스 안에 모두 담아둔다면 자식 중 하나만 변경되어도 모든 자식들을 갱신하는 비용이 있다.
그렇다고 모든 자식들이 캔버스를 갖고있는 것은 비추천. 무거울수 있기 때문. UI 최적화는 케바케가 심하므로 완벽한 정답이 없으니 상황에 맞게 사용하길 권장 (etc: 동적인 객체, 정적인 객체 나눠서 등)
2. 43:30 uI 풀링할때 reparenting 하는 경우가 있는데 저렴한 비용이 아니다. 그 이유는 RectTransform이 계층 구조를 가진 Transform을 상속받고있고, 부모가 바뀌게 되면 본인 포함 자식 개체들을 갱신시켜준다.
(OnBeforeTransformParentChanged, OnTransformParentChanged, OnTransformChildrenChanged)
3. 59:40 3D 같은 경우 Frame Debugger에서 충분히 Batching이 깨진 이유를 설명해주나, UI는 그 원인을 설명을 안해줌. 그러므로 UI는 프로파일러 내에 UI 항목을 확인하는 것이 편함. 어떤 UI를 그려주는 Batching인지 확인할뿐더러 배칭이 깨진 이유를 설명해줌 (ex. Use Different Texture)
4. 1:09:30 블렌딩이 들어가는 쉐이더는, 불투명 X 반투명O, Z값에 따라 나눠 그리기 때문에 (Back-To-Front) Z값을 나누게 될 경우 배칭이 깨지게 된다.
이는 UI에도 적용이 되므로 Z값을 나눠 작업하게되면 배칭이 깨지게 된다.
(번외) 스프라이트 같은 경우 알파값이 0이어도 Active 상태면 렌더링, 더티 대상이다.
5. 1:11:30 Ui 스프라이트의, 특히 동적인 애들, Pixel Perfect는 성능에 많은 악영향을 끼친다. RectTransform 변경 시 모든 정점을 재계산하기 때문이다.
6. 1:16:12 그럼에도 Pixel Perfect를 놓치고 싶지 얂으면, 따로 스크롤링 할 때만 꺼주는 기능을 넣거나 그 외 별도 작업 (ex. Nested Canvas들 중 픽셀퍼펙트가 필요없는 것들은 Off로 설정) 을 해줘야 한다.
7. 1:26:02 Layout 정렬 관련 컴포넌트 (Layout Group, Grid, 등등)은 초기 세팅 시 혹은 요소의 특성(행렬이 적용되는 T•R•S 등) 변경 시에만 Enable해주고 필요없을 땐 Disable을 해주는 것이 좋다.
8. 1:27:00 버튼 같은 경우 여러 가지의 상태 혹은 테두리를 나타내기 위해 각각의 오브젝트를 두지 말고 성능을 위해, 추가작업이 필요하지만, 하나의 버튼 안에서 다 처리해줘야한다. 예를 들어 같은 크기의 Sprite만 변경해줬을 때는 Dirty가 발생하지 않기 때문에 (이건 앞에서 설명해주심) 성능 측면에서 효율적이다.
9. 1:29:40 UI도 스크롤 같이 같은 타입의 개체를 많이 사용해야하는 경우 오브젝트 풀링을 사용하길 권장. (Optimized, Unoptimized 비교하는 모습 보여주시고있음)
10. 1:30:40 버튼 움직임이라든지 화려한 연출을 위해 보통 애니메이터를 사용하는데 애니메이터는 KeyFrame 방식으로 동작하므로, Idle 상태일 때도 Dirty가 발생하니깐 항상 변경되는 UI [Idle일 때도 움직이는]에만 애니메이터를 적용하는 것을 권장한다. 대신에 코드로 된 외부 플러그인 (DoTween)을 사용하거나 직접 코드를 작성해서 애니메이팅 하는 것을 권장한다.
11. 1:34:17 불필요한 이미지의 Raycast Target을 비활성화하고 필요한 곳에서만 Raycaster를 사용
12. 1:36:20 화면 전체를 덮는 UI를 활성화 했으며 뒤에 3d배경이 켜져있을 필요가 없다면 해당 장면을 렌더링하는 카메라를 꺼주거나 빈 곳을 보도록 돌려버려야한다. 하지만, 카메라를 껏다켰다하면 오버헤드가 발생할 수 있으니 다른 곳을 보도록 하는 것이 더 효율적일 수 있다.
13. 1:37:20 전체 화면을 덮는 UI가 활성화되었을 때, UI는 60프레임까지 돌릴 필요없으니, 모바일 기준으로 배터리 및 자원을 아끼기 위해 풀스크린UI 상태에서는 타겟 프레임 레이트를 30으로 낮춘다거나 비슷한 작업을 해주길 권장.
UI관련 접허기 어려운 최적화에 대해 잘 즐겼습니다
항상 건강하십시오 두분😢
와 좋은 내용 감사합니다. 거의 ugui만 사용해서 개발을 하는 중인데, 최적화에서 사용할 수 있을만한 아이디어들이 많이 보이네요!
지나치기 쉬운 부분에 대해 알기쉽게 설명해주셔서 정말 큰 도움이 되었습니다.
screen space- camera, world space 편도 만들어 주실거죠?
UI에 대해 몰랐던 것 많이 알아갑니다.
[1:20:36] 레이아웃을 캔버스를 통해서 잡는 게 성능상 이슈가 덜 하겠네요
알쓸유잡!! 유용해요~
1:24:55 에서 '재구성이 필요할 때 레이아웃을 활성화' 이 부분에서 좀 궁금한 게 있는데
레이아웃을 활성화 한 상태에서 가만히 두어도 SetDirty()가 발생하나요?
테스트 해보니 레이아웃 그룹의 자식을 건들지 않는 이상 SetDirty()가 실행되진 않는 것 같은데
그러면 굳이 레이아웃을 비활성화, 활성화 할 필요 없이 레이아웃을 활성화 한 상태로 두어도 성능 측면에서 이슈가 없지 않나요?
꼭 재구성이 필요할 때 다시 켰다가 끄는 것이 성능에 좋습니까? 그렇다면 정량적으로 얼마만큼 좋습니까?
혹시 레벨 디자인 할때 움직이는 오브젝트들도 Environment 하위 폴더 안에 넣어서 관리하는데 그럼 Environment안에 있는 모든 오브젝트들이 다시 계산되는건가요?
Atlas 했는데 왜 안 바뀔까 했는데 z값에 영향을 받아서 최적화가 안됐구나....랜더모드를 Camera로 하니까 당연히 z값이 다를거고 결국 전부 계산된거네...Overlay로 바뀌니 1/4일로 줄어드네..
이번에 유니티에서 사용료 정책을 바꿨더라구요.. 슬픈 일입니다
질문 있습니다!! ui제작할때 이미지의 갯수를 최대한 줄이는게 최적화에 도움이 되나요?
예를 들어서 단순히 배경 이미지 1장에 각종 장식용 이미지 10개를 각각의 이미지로 배경의 자식으로 넣는거랑
배경이랑 장식용 이미지를 포토샵에서 하나로 합쳐서 넣는거 입니다!!
물론 이미지를 줄이면 부하가 적어지지만 무리한 축소는 컨텐츠의 퀄리티에 영향을 줄 수 있으니 적절한 축소와 배칭을 활용하시는 것이 중요합니다.
캔버스 STATIC 과 DYNAMIC을 나눌때, recttransform이동 말고, Text의 3,2,1과 같이 string문자 변화나 SetActive활성화 비활성화도 다이나믹으로 취급되는건가요?
텍스트도 글자가 변경되면 메시 사이즈가 변경되니 후자로 보시는게 맞을 것 같아요
넵 Text도 마찬가지입니다
난 왜 본방을 놓치는걸까? 트위터 없으세요?
유니티 코리아 채널 구독과 알림 설정 부탁드립니다! 알쓸유잡 라이브는 매월 셋째주 수요일 4시, 유니티 라이브는 매월 마지막주 수요일 4시에 진행됩니다.
@@UnityKoreaHi 이미 하고 있다는게 함정 ㅠㅡㅠ