Unity/수업내용

Unity UI 21.04.23. 수업내용 - 스크롤팝업 만들기

HappyFrog 2021. 4. 23. 11:30

오늘의 재료.

 

미션들은 프리팹으로 아이콘과 별 갯수, 미션 내용을 불러올 예정이며

보상과 버튼은

1. 각각 3개씩 종류별로 만드는 방법(하트, 다이아, 코인 // 완료, 보상받기, 진행중)

ㄴ gameObject.SetActive사용

 

2. 미션처럼 하나만 만들어놓고 코드로 프리팹에 스프라이트 이름과 RGB값, Text값을 할당하여 출력하는 방법이 있다.

 

++ 미션진행 게이지같은 경우는 장식이나 이펙트가 있으면 슬라이더를 사용하고 그렇지 않은 단순한 경우에는 이미지를 사용하는게 편하다.

 

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

(위에꺼 망해서 새로운거로 다시시도 함 ㅎ..)

스크롤을 하는 방법은 의외로 간단했다.

여기서 scrollview와 items를 봐야하는데, scrollview에는 스크롤을 할 수 있게 하는 기능을 넣어줄거고 items(작명을 contents나 goods로 할걸..)는 scroll되는 대상이다.

 

간단하게 scrollview에 scroll Rect를 넣어주면 된다.

그리고 나는 가로로 넘기고 싶으므로 vertical을 체크해제 해 둔뒤 content(스크롤 대상)에 items를 넣어준다.

이러면 스크롤이 되는데, 문제는 지나간 이미지가 페이지 너머서까지 보인다는게 문제가 된다.

이런 문제는 Mask컴포넌트를 scrollview에 추가해주면 깔끔하게 해결된다.

이유는 모르겠지만 scrollview에 이미지컴포넌트를 넣어두니 mask가 잘 작동했다.

 

그리고 프리팹으로 넣어줄 상품들을 예쁘게 정렬해주기 위해서 items에 horizontal layer group컴포넌트를 추가해줬다.

++items에 Content Size Fitter도 꼭 달아주자 안그러면 스크롤이 되는데 영역이 좁아서 다음상품으로 넘어가지 않고 돌아온다. 보이질 않는다.

 

 

 

상점에 들어갈 껍데기(프리팹)은 이렇게 만들었고, 이제 여기에 코드를 이용하여 새로운 상품들을 역직렬화한 데이터들을 이용하여 찍어낼것이다.

 

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

public class ShopPriceData
{
    public int icon_sp_id;
    public string icon_sp_name;
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ShopItemData
{
    public int id;
    public int goods_id ;
    public string goods_sp_name;
    public int amount;
    public int bonus;
    public int price_id;
    public float price;

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

public class UIShopItem : MonoBehaviour
{
    public SpriteAtlas atlas;
    public Image icon;
    public Button btn;
    public Text price;
    public Image price_icon;
    public Text amount;
    public GameObject bonus;
    public Text bonusAmount;
    public GameObject hot;
    public GameObject best;

    private int sellCount;

    private ShopItemData data;

    public void Init(ShopItemData data)
    {
        if (data.bonus != 0)
        {
            this.bonus.SetActive(true);
        }
        if (this.sellCount > 10)
        {
            this.hot.gameObject.SetActive(true);
            this.best.gameObject.SetActive(false);

            if (this.sellCount > 50)
            {
                this.hot.gameObject.SetActive(false);
                this.best.gameObject.SetActive(true);
            }
        }
        this.icon.sprite = this.atlas.GetSprite(data.goods_sp_name);
        this.price.text = data.price.ToString();
        this.price_icon.sprite = this.atlas.GetSprite(DataManager.GetInstance().dicShopPriceData[data.price_id].icon_sp_name);
        this.amount.text = data.amount.ToString();
        this.bonusAmount.text = "Bonus " + data.bonus.ToString() + "%";

        this.btn.onClick.AddListener(() =>
        {            
            this.sellCount++;
            Debug.LogFormat("Thank you :D // Sell : {0}", this.sellCount);
        });

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

public class UIPopupShop : MonoBehaviour
{
    public ScrollView scroll;
    public Button btnGold;
    public Button btnGem;
    public Button btnSoulGem;


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

    // Update is called once per frame
    void Update()
    {
        
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Newtonsoft.Json;
using System.Linq;

public class DataManager
{
    public Dictionary<int, ShopItemData> dicShopItemData;
    public Dictionary<int, ShopPriceData> dicShopPriceData;

    private static DataManager instance;

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

    public void LoadData()
    {
        var ta = Resources.Load<TextAsset>("Datas/shop_item_data");
        var json = ta.text;
        this.dicShopItemData = JsonConvert.DeserializeObject<ShopItemData[]>(json).ToDictionary(x => x.id);

        var priceTa = Resources.Load<TextAsset>("Datas/shop_price_data");
        var priceJson = priceTa.text;
        this.dicShopPriceData = JsonConvert.DeserializeObject<ShopPriceData[]>(priceJson).ToDictionary(x => x.icon_sp_id);
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ScrollView : MonoBehaviour
{
    public Transform contents;
    public GameObject itemPrefab;
    public ShopItemInfo info;

    // Start is called before the first frame update
    void Start()
    {
        DataManager.GetInstance().LoadData();

        foreach (var pair in DataManager.GetInstance().dicShopItemData)
        {
            var go = Instantiate(this.itemPrefab, this.contents);
            var goods = go.GetComponent<UIShopItem>();
            var data = pair.Value;
            goods.Init(data);



        }
    }

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

    }
}

 이런식으로 만들었다. UIShopItem에서는 받은 데이터를 기반으로 Init메서드를 사용하여 프리팹에 불러온 데이터를 삽입하여 그를 기반으로 이미지와 텍스트들을 불러온다. 나는 scrollview에서 loadData를 했지만, scrollview의 start에 있는 기능들을 Init메서드로 만들어준다면 UIPopupShop(가장 상위계층)에서 불러올 수 있을것 같다.

 

++버튼을 눌렀을때 sellCount가 올라가고 이미지들이 SetActive되는것은 아직 시험하지 않았다.

 

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

1000원짜리를 30번 눌렀지만 HOT, BEST휘장이 뜨지않는다.

 

조건문을 onClick이벤트 안에 넣어주니 잘 작동한다. 하지만 Debug메시기는 따로따로 출력되지 않는 모습이다.

 

디버그 메시지를 이런식으로 ID에 따라 구분해주었더니 객체마다 다른 수가 출력되며 정상작동한다.

 

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

이런식으로 UIPopupShop, ScrollView를 고쳐썼다니 페이지를 바꿀 때마다 새로운 상품들이 받아진다. 초깃값은 Start에 미리 써 두던가 onClick이벤트들 위쪽에 코드를 써두면 골드 초기화면이 출력될 것 같다. 하지만 문제가 있다.

각 버튼들을 눌렀더니 기존 데이터에 새로운 데이터가 덧씌워져서 그런지 버튼 두개가 동시에 눌리는 모습이다.

 

+초기화를 해야할 것 같은데 방법을 잘 모르겠다.