'Unity Engine/NGUI'에 해당되는 글 3건

  1. 2019.06.20 [NGUI] Infinite ScrollView (AT) 1
  2. 2018.12.21 NGUI #02.UIPanel
  3. 2018.12.18 NGUI #01.UIRoot
posted by REDFORCE 2019. 6. 20. 15:59

최근 회사에서 채팅UI의 구조 개선에 대한 이슈가 발생하여 만들어두었던 채팅창을 모두 갈아엎게 되었다.

기존의 채팅 UI구조는 채팅메세지가 들어올 때마다 Instantiate ( ) 가 수행되어 말풍선 UI가 계속해서 쌓이는 구조였다.

 

물론 처음 개발 당시엔 채팅메세지가 엄청나게 쏟아지는 경우를 고려하여 말풍선이 쌓이는 갯수를 최대 200개 까지로 제한하여 그 이상 메세지가 쌓일 시엔 가장 오래 된 메세지를 삭제하고 새로 생성하는 형태로 구현했었다.

(Mobile : Android/iOS) Astrokings(아스트로킹즈)

워낙 게임이 채팅이 많이 오가는 게임이 아니라서 (개인적으론 그렇게 생각한다..) 딱히 위 설계대로 구현한 당시엔 큰 문제나 이슈는 없었다.


그러나 오랫동안 접속상태를 유지한 채, 채팅창을 한번도 키지않고 있다가 새로운 메세지가 많이 쌓인 상태에서 채팅창을 킬 시 200개의 메세지를 모두 갱신하느라 하드웨어에 따라 다르지만 약 3~10초 이상의 딜레이가 걸리는 문제로 결국 인해 최적화 이슈가 발생했다.

 

이 문제를 어떻게 해결할까 하다가 결국 Infinite ScrollView의 필요성을 느끼게 되었고, 여러가지 InfiniteScrollView에 대한 Reference를 찾아보고 적용해보았지만 가장 큰 문제가 있었다.

 

구글, 스택오버플로우 등 다양한 곳에서 찾아본 Infinite ScrollView는 100% Grid 형태의 모든 스크롤 항목이 동일한 크기임을 전제로 하여 만들어져 있었다. 그러나 필자가 필요로 하는 Infinite ScrollView의 경우 채팅창의 말풍선들이 내용에 따라 가변적으로 크기가 변하는 조건이 있어서 사람들이 흔히 쓰는 방식으로는 구현할 수가 없었다.

 

결국...NGUI의 UITable 의 Reposition 기능과 더불어 ScrollView의 기능을 자동으로 수행해줄 수 있는 Infinite ScrollView

를 따로 만들게 되었다.

 

[AT] Infinite ScrollView

혹시나 필자가 만들어둔 ScrollView를 사용할 사람들을 위해 주의사항을 몇가지 작성해둔다.

 

1. 각 스크롤 되는 아이템 항목은 가변적으로 늘어나되, 가변으로 아이템의 크기가 변경되는 사항은 NGUI Anchor를 이용한다는 전제로 구현되어 있다.

2. Prefab으로 연결 시킬 Item의 크기에 따라 자동으로 내부의 Pooling이 결정 된다.

3. 여러개의 Column을 지원하지만, 1 Column 체제로 사용하는 것을 추천한다.

4. 필자는 Vertical 기능만 있으면 되서 Horizontal 은 구현하지 않았다. (Horizontal 부분은 구조만 잡혀있다)

5. SetFocus 기능을 이용하면 해당 아이템을 기준으로 Refresh 된다. (Panel 이 Spring 되는 것이 아니다)

6. Position 계산의 Pivot은 Top이 기준이다.

7. Default 설정 값은 가급적 그대로 두고 사용하길 추천한다 (One Direction, Flat, Horizontal 등. 미완성 내용이 많다)

8. Prepare Size 는 Pool에서 미리 잡아두는 예비 Item 사이즈이다. (2~4정도면 적절, Column 갯수가 늘어난다면 문제가 발생할 수 있다)

 

결국 Pooling 형태의 Infinite ScrollView로 변경한 결과, 오래 된 내용이 있을지라도 Instantiate ( ) 를 하지 않고 현재 보여질 내용만 갱신하게 되어 속도와 메모리 측면에서 상당히 좋은 결과를 얻을 수 있었다.

 

다만 단점은 갱신 되는 Item의 크기와 예비 갯수에 따라 스크롤이 매끄럽게 계속해서 이어가다가 끊기는 현상이 다분히 발생할 수 있다.

 

 

아래는 원본 Infinite ScrollView Class Code이다.

 

'Unity Engine > NGUI' 카테고리의 다른 글

NGUI #02.UIPanel  (0) 2018.12.21
NGUI #01.UIRoot  (0) 2018.12.18
posted by REDFORCE 2018. 12. 21. 00:53

Unity 2018.2.1f1 - NGUI 3.12.0 을 기반으로 작성 되었습니다.

-----------------------

이번에 작성할 내용은 UIRoot에 이어서 UIPanel입니다.




UIPanel 은 NGUI의 UIWidget들이 담겨져서 보여지게 되는 일련의 가장 뒷편에 깔리는 도화지 같은 개념이라 보시면 됩니다.


 

 설명

 Alpha 


 해당 패널의 Hierarcy 구조상 하위에 붙은 모든 Widget들의 Alpha에 영향을 미치는 값 입니다. 하위에 붙어있는 Panel에는 영향을 주지 않습니다.

 

 Depth


 만약 UIPanel이 2개 이상 UIRoot에 자식으로 활성화되어 있을 시

먼저 보여지게 될 순서를 의미합니다.


 Clipping


 특정 영역을 설정하고 그 영역 밖에 있는 부분을 렌더링하지 않는 것을 의미합니다.


 > None : 클리핑을 하지 않습니다.

 > Texture Mask : 등록 된 Texture 영역을 제외하고 클리핑 합니다.

 > Soft Clipping : 패널 영역을 설정하고 클리핑 합니다. Softness 값을 주어 외곽부분을 부드럽게 클리핑 되도록 합니다.

 > Constrained But Dont Clip : 패널 영역을 지정하지만 클리핑은 하지 않습니다.


 Advanced Options

  

 Render Q :
  - Rendering 되어질 때의 순서를 정할 수 있습니다.

  - UI에 Particle System 을 사용하는 상황 같은 Render Queue 경쟁이 벌어질 수 있는 환경에서 설정하는 값 입니다. 

 Sort Order :
  - 같은 DEpth에서 렌더링 순서를 결정합니다.
  - Unity Sprite의 OrderInLayer와 유사합니다.
  - 높을 수록 위에 출력됩니다.

 Normal : 체크하면 패널이 Light에 영향을 받습니다.

 Cull : ScrollView 패널에서 성능 향상을 위해 사용되어지는 옵션입니다. 패널이 드래그(Drag) 되어 Widget이 패널 영역을 벗어날 시 자식위젯들을 Rendering 하지 않습니다.

 Visible : 패널 내부의 Widget들이 스크린 안에 있는지 계산하여 Rendering 여부를 결정하는 데, 이 계산을 건너띄게 만듭니다.
UIWidget 들이 패널을 벗어날 일이 없을 경우 체크하게 되면 성능이 향상 됩니다.

 Padding : 패널의 외각 부분을 부드럽게 만듭니다.
 (클리핑 옵션이 Softness 인 상태에서는 의미는 없는 듯)

 Static : 패널 내의 위젯들이 이동이 없는 경우 Static으로 설정하면 유니티가 Position, Rotation, Scale 값을 계산하지 않아 성능이 향상 됩니다.


 Anchors


  UIPanel 또는 UIWidget 에서 특정 위치를 기준으로 좌표가 잡히도록 설정하는 값 입니다.


 Show Draw Calls

 Draw Call Tool 창을 불러옵니다.


'Unity Engine > NGUI' 카테고리의 다른 글

[NGUI] Infinite ScrollView (AT)  (1) 2019.06.20
NGUI #01.UIRoot  (0) 2018.12.18
posted by REDFORCE 2018. 12. 18. 01:49

Unity 2018.2.1f1 - NGUI 3.12.0 을 기반으로 작성 되었습니다.


---------------------------


NGUI는 Unity에서 UI를 제작하는데 많이 사용되고 있는 UI Plugin이다.


Unity(Unity GUI)가 과거(대략 유니티3.0 시절) 너무나 구닥다리 거지깽깽이 같은 기능성을 제공하는 바람에 Next-Gen UI Kit 이라고해서 Tasharen Entertainment에서 만들었다.


이 글을 작성하는 시점인 현재는 NGUI 개발자가 유니티에 스카웃되어 UGUI를 개발하고 있다고 알고 있다. 덕분에 UGUI가 옛날에 비하여 상당히 편해지고 좋아졌으나 아직까진 한국에서는 NGUI의 비중이 40% 이상인 것으로 알고 있다.


과거 NGUI가 흥하던 시절에는 NGUI 사용량이 UGUI에 비해 8~90%에 육박하였다.

역사적인 서론은 여기까지하고...


이 글을 적는 목적은 구글에서 NGUI에 대해서 검색할 시 흔히 볼 수 있는 글들이 너무나 오래 된 글들이 많아서 최신 버전을 사용하는 사람들에게는 생소하거나 동작되지 않거나 삭제되거나 변경 된 사항들이 자주 등장하다보니 삽질을 하는 일이 많아서 작성하게 되었다.


(사실 본인이 제일 삽질하는 바람에 답답해서 적게되었다)


---------------------------


#1. UIRoot


NGUI가 Project에 포함되어 있다면 위와 같이 상단 Toolbar에 "NGUI" 가 보입니다.



상단 툴바에서는 

 - Selection, Create, Attach, Tween 등 다양한 기능들이 들어있습니다.

각 항목을 모두 설명하는 것은 내용이 너무 많으므로 차근차근 사용해가면서 설명하겠습니다.



먼저 NGUI가 작동하려면 UIRootUICamera가 필요합니다.


간단하게 먼저 비어있는 Scene에서 NGUI > Create > Texture를 눌러보겠습니다.



위 사진처럼 Texture를 누르면 2번 항목과 같이 UIRoot와 Camera 그리고 Create에서 Texture를 했으므로 UITexture 컴포넌트가 붙은 "Texture" 이름을 가진 GameObject가 생성됩니다.



생성 된 UIRoot 를 선택해서 Inspector 창에 보여지는 정보를 살펴보면 다음과 같이 나옵니다.



UIRoot - 

 UIRoot 컴포넌트는 UIWidget을 상속받은 컴포넌트 및 오브젝트들의 최상단 패널로써,

해상도 또는 크기를 조절할 수 있는 스케일링 역할을 담당합니다.


UIRoot에는 다음과 같은 파라미터가 있습니다.


 파라미터

 설명

 Scaling Style

 1) Flexible : 화면 해상도에 관계 없이 UI가 픽셀 단위에서 언제나 같은 크기를 유지함. 실제 해상도에 따라 보여지는 크기가 작아지거나 커질 수 있음


 2) Constrained : UI가 화면에서 항상 같은 비율로 보이도록 스케일링 합니다. UI의 오리지날 픽셀 단위의 크기가 비율에 맞춰져 변동될 수 있음


 3) ConstrainedOnMobiles : 모바일 플랫폼에서는 Constrained 방식을 사용, 기타 플랫폼에서는 Flexible 방식을 사용합니다.


 Minimum Height

 

Flexible 방식에서 화면의 최소 높이 값을 지정합니다. 화면 높이가 설정한 값보다 작아지면 UI 크기를 조정합니다.


 Maximum Height

 

Flexible 방식에서 화면의 최대 높이를 지정합니다. 화면 높이가 설정한 값보다 커지면 UI 크기를 조정합니다.



UIRoot를 설정함에 있어 가장 중요한 점은 본인이 만드는 프로젝트의 기본 해상도를 어떻게 잡는지가 중요합니다.


16:9 비율을 쓸 것인가 4:3 비율을 쓸 것인가

1920x1080해상도를 기준으로 잡을 것인가 1280x720 해상도를 기준으로 잡을 것인가

등등, 모바일 플랫폼이라면 안드로이드 기기 별 해상도 차이가 심하기 때문에 고민하게 됩니다.


모바일 플랫폼에서는 이에 대응하기 위해 보통 ConstrainedOnMobiles 로 설정합니다.


ConstrainedOnMobiles로 설정하면 다음과 같이 Content Width, Content Height로 기준 해상도를 설정할 수 있습니다.



1) Content Width/Height 둘중 하나만 Fit 활성화 : 체크 된 항목의 비율을 유지하여 스케일링 됩니다.


2) Width/Height Fit 모두 비활성화 : 기기 해상도에 맞추어 UI가 늘어나지만 Camera에 모든 UI가 들어오지 않을 수 있습니다.


3) Width/Height Fit 모두 활성화 : 강제로 UI 항목들이 스케일링 되어 항상 화면에 보여지게 됩니다.


Fit를 둘다 체크할 시 UI 전체 화면이 스케일링 되어 UICamera에 보여질 수 있으나

기기 해상도 차이로 인해 발생하는 공백 부분은 메인카메라에 설정된 Background 값으로 채워집니다.


현재 회사에서 개발중인 게임(모바일)의 경우 


ConstrainedOnMobile 

 > Content Width(1280) Fit(Disable)

 > Content Height (720) Fit(Enable)


인 상태에서 NGUI의 앵커를 이용하여 해상도를 대응하고 있습니다.


모바일 플랫폼에서 그래서 UIRoot를 어떻게 설정하고해라 라는 정답은 없습니다만 최근 AppStore나 GoogleStore에서 요구하는 정책 사항을 고려해볼 때 위와같이 설정하여 앵커로 해상도를 대응하는 방식으로 가야하지 않을까 생각합니다.


(AppStore의 경우 Letter Camera를 사용하면 안됨. 2018년 기준)

좀 더 편한 방법이 있다면 저도 알려주세요.


UIPanel 에 대해서는 다음글에서 다루고 있습니다


RigidBody - 

 마지막으로 UIRoot에는 RigidBody Component가 붙습니다. 만약 RigidBody가 안 붙어 있다면 NGUI의 Widget들의 Event를 동작시킬 수 없습니다.


버튼, 스크롤, 스위치, 패널 등 Widget에서의 Click, Touch, Press, Drag 등의 Event를 검출하기 위해 붙어 있습니다.

'Unity Engine > NGUI' 카테고리의 다른 글

[NGUI] Infinite ScrollView (AT)  (1) 2019.06.20
NGUI #02.UIPanel  (0) 2018.12.21