본문 바로가기

Game/Unity

[NGUI] ScrollView 만들기

리소스 준비

아래의 화면 갈무리와 같이 리소스를 준비합니다. 화면에 표시될 이미지 파일들과 Label에서 사용할 폰트 파일입니다. 이 예제에서는 Label에서 사용할 폰트를 `나눔고딕`체로 사용하기 위하여 `다이나믹 폰트` 기능도 함께 사용하고 있습니다. 폰트 파일은 네이버를 통해서 다운받을 수 있습니다.


ngui-scrollview-00.png




스크롤 뷰 구조 구성하기

스크롤 뷰의 오브젝트 구조를 만들기 위하여 가장 먼저 NGUI의 2D UI를 준비합니다.


ngui-scrollview-01.png




여기에서는 모바일 장치에 맞는 화면 크기를 기준으로 삼고 있습니다. 그래서 NGUI의 `UI Root`에 대한 `Scaling Style` 속성을 `FixedSizeOnMobiles`로 변경하고 `Manual Height`값을 800으로 설정합니다.


ngui-scrollview-02.png




`UI Root` 하위에 `Scroll View` 오브젝트를 생성합니다.


ngui-scrollview-03.png




`Scroll View`의 가로 크기를 700으로 설정합니다. 핸드폰 장치에서 가로뷰 형태로 진행되는 게임이라고 가정했을 때, 전체 크기가 800이므로 스크롤 영역을 700으로 지정하면 화면의 약 87% 정도를 차지하는 면적이 될 것입니다.


ngui-scrollview-04.png




`Scroll View` 하위에 `Grid` 오브젝트를 생성합니다. 이 안에 각각의 아이템들이 배치되게 됩니다.


ngui-scrollview-05.png




`Grid`에서 한 칸의 크기를 120x200으로 설정하기 위하여 `Cell Width` 속성과 `Cell Height` 속성을 설정합니다. 그리고 스크롤 시에 부드러운 애니메이션 처리를 위하여 `Smooth Tween` 속성을 체크합니다.


ngui-scrollview-06.png




`Grid`를 선택하고 `Inspector` 창에서 `Add Component` 버튼을 누릅니다.

"NGUI > Interaction > Center Scroll View On Child" 항목을 선택하여 스크립트 컴포넌트를 추가합니다.


ngui-scrollview-07.png





아이템 항목 만들기

일반적으로 `Grid`안에 포함될 아이템 항목은 여러 개의 오브젝트가 하나로 묶인 형태가 될 것입니다. 여러 개의 오브젝트에 대한 컨테이너의 역할을 할 빈 오브젝트를 씬에 추가합니다.


ngui-scrollview-08.png




추가된 `GameObject`를 "UI Root > Scroll View > Grid > ... "의 하위로 위치하도록 드래그하여 배치합니다.

이 오브젝트의 이름을 `Item`으로 설정해 주고, Scale 속성을 모두 1로 초기화 합니다. Main Camera와 NGUI의 카메라가 서로 비율이 다르기 때문에 이 오브젝트가 Grid의 하위로 이동하는 순간 Scale의 비율이 변하게 됩니다.

또한 이 요소는 NGUI의 영향을 받아야 하므로, NGUI 요소들이 공통적으로 소속되는 `UI`레이어로 변경해 주어야 합니다.


ngui-scrollview-09.png




이렇게 준비된 `Item` 오브젝트에게 `Drag Scroll View` 컴포넌트를 추가합니다. 이 컴포넌트는 "NGUI > Interaction" 하위에 존재합니다. 이 스크립트가 드래그 했을 때, 스크롤이 되도록 처리하는 역할을 합니다.


ngui-scrollview-10.png




같은 방식으로 `Center Scroll View on Click` 스크립트를 추가합니다. 이 스크립트의 기능은 특정 항목을 클릭(터치) 했을 경우 그 요소가 Scroll View의 중앙으로 오도록 합니다. 이 기능을 원치 않는다면 이 과정을 생략해도 됩니다.


ngui-scrollview-11.png




Item의 하위에 포함될 이미지를 표시하기 위하여 `Texture`를 추가합니다. 여기에서는 스크립트를 통하여 이미지를 지정해 줄 것이므로 오브젝트를 추가하기만 합니다.


ngui-scrollview-12.png




이번에는 `Item`의 하위에 Label 요소를 추가합니다. 이 오브젝트는 이미지 하단에 텍스트를 표시하는 역할을 하게 됩니다.


ngui-scrollview-14.png




아래의 화면 갈무리를 참고하여 Label에 나눔고딕 폰트를 연결해 줍니다.


ngui-scrollview-15.png




Label의 Y축 Position을 -65로 설정하여 이미지 아래에 위치하도록 지정하여 줍니다.  다이나믹 폰트를 사용할 경우 그라디언트 처리는 오히려 텍스트를 흐릿하게 보이게 하므로 `Gradient` 속성의 체크를 해제하고, `Effect` 속성을 `Outline`으로 설정합니다. 이 속성을 사용하면 텍스트에 외각선이 그려집니다.


ngui-scrollview-16.png




이 과정이 매우 중요합니다. Scroll View 하위에 포함된 요소들은 스크롤되기 위하여 사용자가 터치해서 이동시키게 될 것입니다. 이 때, 각 아이템의 항목에 대한 터치 좌표를 인지하기 위한 `Collider`가 반드시 추가되어야 합니다.

Hierachy 뷰에서 `Item` 오브젝트를 선택한 상태로 "NGUI > Attach > Collider" 항목을 선택합니다.


ngui-scrollview-17.png




우리는 앞서 Gird에서 Cell Width를 120으로 설정 하였습니다. 한 칸 안에서 터치 영역의 크기도 Cell Width와 동일하게 맞춰 줍니다. 그 밖에 Scene 뷰를 보면서 Collider가 이미지와 텍스트를 온전하게 감쌀 수 있도록 Center 속성도 수정합니다.


ngui-scrollview-18.png




이제 완성된 Item을 프리팹으로 등록하기 위하여 Project 뷰에 드래그 해서 넣고, Hierarch 뷰의 Item은 삭제합니다.


ngui-scrollview-19.png





동적 구성을 위한 스크립트 작성

Item 프리팹을 참조하여 객체를 동적으로 생성하고 Grid에 추가하기 위한 스크립트를 다음과 같이 작성합니다.


Grid.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
using UnityEngine;
using System.Collections;
 
public class Grid : MonoBehaviour {
 
    // `Item` 프리팹이 연결될 객체
    public GameObject item;
    // Grid 에서 표시하고자 하는 이미지들이 저장될 Texture 배열
    public Texture[] images;
     
    /** 처음 객체가 로딩될 때, 초기화 함수 호출 */
    void Start () {
        InitItem();
    }
 
    /** Grid 초기화 */
    void InitItem() {
        // 이미지의 수 만큼 반복합니다.
        for (int i = 0; i < images.Length; i++) {
            //일단 생성합니다. 무조건...
            GameObject obj = Instantiate(item, new Vector3(0f, 0f, 0f), Quaternion.identity) as GameObject;
             
            //생성된 GameObject의 부모가 누구인지 명확히 알려줍니다. (내가 니 애비다!!)
            obj.transform.parent = this.transform;
             
            //NGUI는 자동이 너무많이 짜증나니 수동으로 Scale을 조정해줍니다.
            obj.transform.localScale = new Vector3(1f, 1f, 1f);
             
            // Item 하위의 자식 요소들에 대한 객체를 얻어냅니다.
            UITexture texture = GetChildObj (obj, "Texture").GetComponent<UITexture>();
            UILabel label = GetChildObj (obj, "Label").GetComponent<UILabel>();
 
            // 자식 객체들에게 이미지와 텍스트를 출력.
            texture.mainTexture = images[i];
            label.text = (i+1).ToString();
        }
         
        //Prefab을 생성한 이후에 Position이 모두 같아서 겹쳐지므로 Reposition시키도록 합니다.
        GetComponent<UIGrid>().Reposition();
    }
 
    /** 객체의 이름을 통하여 자식 요소를 찾아서 리턴하는 함수 */
    GameObject GetChildObj( GameObject source, string strName  ) {
        Transform[] AllData = source.GetComponentsInChildren< Transform >();
        GameObject target = null;
         
        foreach( Transform Obj in AllData ) {
            if( Obj.name == strName ) {
                target = Obj.gameObject;
                break;
            }
        }
         
        return target;
    }
}





위와 같이 작성된 스크립트를 아래의 화면 갈무리와 같이 Hierarchy 뷰의 Grid에게 컴포넌트로 등록시킵니다.


ngui-scrollview-20.png




Grid에 추가된 스크립트에서 선언하고 있는 Item 객체에는 미리 만들어 둔 'Item' 프리팹을 연결해 줍니다.

Images 배열은 사이즈를 12로 설정합니다.


ngui-scrollview-21.png




사이즈가 설정되고 나면 그 하위에 Element 들을 등록할 수 있는 입력칸이 늘어납니다. 이 곳에 이미지 Texture를 등록해 줍니다.


ngui-scrollview-22.png




지금까지의 중간 결과 입니다.


ngui-scrollview-23.png





선택한 항목 감지하기

사용자가 터치한 항목을 인식하기 위하여 다음의 스크립트를 작성합니다.


ItemClick.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
using UnityEngine;
using System.Collections;
 
public class ItemClick : MonoBehaviour {
    // Item 객체가 스스로 인식하게 될 index 값
    int index;
 
    void Start() {
        // 일단 0으로 초기화
        index = 0;
 
        // Item 객체의 부모(=Grid) 하위의 모든 자식요소(=Item들)을 스캔한다.
        foreach (Transform child in this.transform.parent) {
            // 특정 자식 요소와 나 자신이 동일하다면 반복을 멈춘다.
            if (child == transform) {
                // 여기서 멈추게 되면, 현재의 index값이 나 스스로의 번호가 된다.
                break;
            }
            // 인덱스 값을 1씩 증가한다.
            index++;
        }
 
    }
 
    // 클릭했을 때 실행될 이벤트 함수
    void OnClick() {
        Debug.Log (index + "번 째 아이템 클릭됨");
    }
}





`Item` 프리팹에 버튼과 같이 클릭했을 경우의 이벤트를 처리하도록 하기 위해서 "NGUI > Interaction > Button" 스크립트를 컴포넌트로 추가합니다.


ngui-scrollview-24.png




앞서 작성한 Item.cs 스크립트로 컴포넌트로 추가합니다. 그리고 이 스크립트를 Button 스크립트의 `Notify` 속성에 연결시켜 주면, Scroll View의 항목이 터치되었을 때 Button 스크립트를 통하여 Item.cs의 OnClick() 함수가 실행될 것입니다.


ngui-scrollview-25.png




결과 입니다. 스크롤과 터치시에 대한 로그 출력이 잘 되고 있습니다.


ngui-scrollview-26.png





이제 즐깁시다~!!


출처 : http://www.itpaper.co.kr/?mid=unity&document_srl=14082&listStyle=viewer