Notice
Recent Posts
Recent Comments
Link
«   2025/08   »
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
Archives
Today
Total
관리 메뉴

행복한 개구리

Unity NGUI 21.04.27. 수업내용 - 스크롤뷰 만들기 본문

Unity/수업내용

Unity NGUI 21.04.27. 수업내용 - 스크롤뷰 만들기

HappyFrog 2021. 4. 27. 14:42

NGUI에서는 스크롤뷰를 만들 때 한 오브젝트에 ScrollView 스크립트를 넣어야 한다. 빈 객체를 만들어서 컴포넌트를 추가할 수도 있지만 NGUI메뉴에서 생성-스크롤 뷰를 누르면 스크립트가 바인딩된 채로 생성된다.

 

그리고 그 아래에는 Grid를 만들어서(마찬가지로 컴포넌트 추가 or 메뉴에서 생성) 스크롤 할 객체들을 정돈할 수 있도록 한다.

 

스크롤뷰엔 패널 요소도 추가해야한다.

이러면 스크롤뷰 완성이다. Grid아래쪽에 스크롤할 때 보여줄 객체들을 만들고 그 객체들에 각각 Collider와 Drag Scroll이라는 스크립트를 추가해준다.

Collider는 당연히 객체크기만큼 지정해주어야하고 Drag Scroll VIew의 Scroll View는 비워놔도 된다.(플레이를 하면 알아서 할당된다.)

 

이런 식으로 작동되며 나는 Grid를 비워두고 Grid의 자식들로 상품프리팹들을 생성시켜 배치할 예정이다.

 

 

Project레이어에 있는 프리팹 두가지로 상품들을 구현할 것이다. 프리팹들은 껍데기가 되어줄 것이고 알맹이는 데이터를 코드로 보내서 채워줄 것이다. 1번아이템은 광고버튼도 있기 때문에 프리팹을 따로 하나 더 만들었고 스크립트 또한 UIShopAdItem으로 만들어서 UIShopItem을 상속받았다.

 

이런식으로 불러오게 된다. 또한, 데이터 테이블에서 가져올 아이콘들과 상단의 Popular 혹은 Best를 띄우는 여부를 정해뒀기 때문에 각자 모두 다르게 나온다.

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Newtonsoft.Json;
using System.Linq;

public class DataManager
{
    public Dictionary<int, ItemData> dicItemData;
    static DataManager instance;

    public static DataManager GetInstance()
    {
        if(instance == null)
        {
            instance = new DataManager();
        }
        return instance;
    }

    public void LoadDatas()
    {
        var ta = Resources.Load<TextAsset>("Datas/item_data");
        var json = ta.text;
        this.dicItemData = JsonConvert.DeserializeObject<ItemData[]>(json).ToDictionary(x => x.id); ;

    }
}

DataManager를 사용하여 데이터를 불러온다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class UIShopItem : MonoBehaviour
{    
    public UIButton btnBuy;
    public UISprite icon;
    public UILabel name;
    public UILabel price;
    public GameObject badge;
    public UISprite badgeIcon;
    public UILabel badgeText;
    
    
    // Start is called before the first frame update
    void Start()
    {
        
    }

    public virtual void Init(ItemData data)
    {
        this.btnBuy.onClick.Add(new EventDelegate(() => { Debug.Log("Buy"); }));

        this.icon.spriteName = data.sp_name;        
        this.name.text = data.name;
        this.price.text = data.price.ToString();        

        if(data.popularity != 0)
        {
            this.badge.SetActive(true);
            switch (data.popularity)
            {
                case (1):
                    {
                        this.badgeIcon.spriteName = "label_flag_small_red";
                        this.badgeText.text = "POPULAR";
                        Debug.LogFormat("ID : {0} // Pop : {1}", data.id, data.popularity);
                    }
                    break;
                case (2):
                    {
                        this.badgeIcon.spriteName = "label_flag_small_Blue";
                        this.badgeText.text = "BEST";
                        Debug.LogFormat("ID : {0} // Pop : {1}", data.id, data.popularity);

                    }
                    break;
            }           
        }
        
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

그리고 상속시킬 UIShopItem에서 기본적인 내용들을 모두 만들어준다. 또한, UIShopAdItem에서 Init의 내용을 추가할 것이기때문에 메서드 타입 앞에 virtual을 추가한다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class UIShopAdItem : UIShopItem
{
    public UIButton btnAd;
       
    void Start()
    {
        
    }

    public override void Init(ItemData data)
    {
        this.btnAd.onClick.Add(new EventDelegate(() => { Debug.Log("AD"); }));
        
        base.Init(data);
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

UIShopAdItem은 UIShopItem을 상속받고 메서드를 변경하기 위해 타입 앞에 override를 추가하고 추가할 내용과 기존의 Init을 불러오게 했다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ItemData : MonoBehaviour
{
    public int id;
    public string name;
    public string sp_name;
    public int price;
    public int popularity;    
    public string badge_sp_name;
    public string badge_text;   
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class UIShop : MonoBehaviour
{
    public GameObject prefab;
    public GameObject adPrefab;
    public UIGrid grid;

    
    void Start()
    {
        Init();
    }

    public void Init()
    {
        DataManager.GetInstance().LoadDatas();
        
        for(int i = 0; i < DataManager.GetInstance().dicItemData.Count; i++)
        {
            if(i == 0)
            {
                var adGo = Instantiate(this.adPrefab, this.grid.transform);
                var adUiItem = adGo.GetComponent<UIShopAdItem>();
                var adData = DataManager.GetInstance().dicItemData[i];
                adUiItem.Init(adData);
            }
            else
            {
                var go = Instantiate(this.prefab, this.grid.transform);
                var uiItem = go.GetComponent<UIShopItem>();
                var data = DataManager.GetInstance().dicItemData[i];
                uiItem.Init(data);
            }            
        }        
    }    
}

마지막으로 이 모든 내용들을 상위 오브젝트인 UIShop에서 종합적으로 실행시키며 프리팹과 위치를 불러와 불러온 프리팹에 데이터를 넣고 불러온 위치에 배치시킨다.

 

============================================================================

위 내용과 마찬가지로 만든 미션씬이다. 다만 이 씬에서는 미션이 완료됐는지 여부를 통해 버튼이 나타나며 보상을 수령할 수 있고 완료 팝업(빨간색 마름모)이 뜨게끔 할 수 있다. 데이터 불러오기엔 성공했지만 정보불러오기를 아직 안해서 Total골이 라벨값으로 나오는 모습이다. DailyMissionRewards와 탭버튼도 아직 마감하지 못했다.

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class UIMission : MonoBehaviour
{
    public GameObject prefab;
    public UIGrid grid;

    // Start is called before the first frame update
    void Start()
    {
        Init();
    }

    public void Init()
    {
        DataManager.GetInstance().LoadDatas();
        foreach (var pair in DataManager.GetInstance().dicMissionData)
        {
            var data = pair.Value;
            var info = InfoManager.GetInstance().dicMissionInfo[data.id];
            var go = Instantiate(this.prefab, this.grid.transform);
            var mission = go.GetComponent<UIMissionItem>();
            mission.Init(data);
        }        
    }
}
    
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Newtonsoft.Json;
using System.Linq;

public class DataManager
{
    public Dictionary<int, MissionData> dicMissionData;
    public Dictionary<int, ItemData> dicItemData;
    static DataManager instance;

    public static DataManager GetInstance()
    {
        if(instance == null)
        {
            instance = new DataManager();
        }
        return instance;
    }

    public void LoadDatas()
    {
        var ta = Resources.Load<TextAsset>("Datas/item_data");
        var json = ta.text;
        this.dicItemData = JsonConvert.DeserializeObject<ItemData[]>(json).ToDictionary(x => x.id); ;

        var mTa = Resources.Load<TextAsset>("Datas/mission_data");
        var mJson = mTa.text;
        this.dicMissionData = JsonConvert.DeserializeObject<MissionData[]>(mJson).ToDictionary(x => x.id);

    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MissionData
{
    public int id;
    public string title;
    public string desc;
    public string icon_sp_name;
    public string reward_sp_name;
    public int reward_amount;
    public string goal;    
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class UIMissionItem : MonoBehaviour
{
    public UISprite icon;
    public UILabel title;
    public UILabel titleDesc;
    public UISprite rewardIcon;
    public UILabel rewardAmount;
    public UIButton claim;
    public UISlider pgsGauge;
    public UILabel current;
    public UILabel goal;
    public GameObject onDoingGo;
    public GameObject isDoneGo;
// Start is called before the first frame update
void Start()
    {

    }

    public void Init(MissionData data)
    {
        this.icon.spriteName = data.icon_sp_name;
        this.title.text = data.title;
        this.titleDesc.text = data.desc;
        this.rewardIcon.spriteName = data.reward_sp_name;
        this.rewardAmount.text = data.reward_amount.ToString();
        this.goal.text = this.goal.ToString();
    }    
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MissionInfo
{
    public int id;
    public bool isCompleted;
    public bool isClaimed;    
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
using Newtonsoft.Json;
using System.Linq;

public class InfoManager
{
    public Dictionary<int, MissionInfo> dicMissionInfo;
    static InfoManager instance;

    public static InfoManager GetInstance()
    {
        if(instance == null)
        {
            instance = new InfoManager();
        }
        return instance;
    }

    public void LoadInfos()
    {
        var path = string.Format("{0}/mission_info.json", Application.persistentDataPath);
        if (File.Exists(path))
        {
            var json = File.ReadAllText(path);
            this.dicMissionInfo = JsonConvert.DeserializeObject<MissionInfo[]>(json).ToDictionary(x => x.id);
        }
        else
        {
            Debug.Log("There's no file... :(");
        }

    }
}