Unity UI 21.04.23. 수업내용 - 스크롤팝업 만들기
오늘의 재료.
미션들은 프리팹으로 아이콘과 별 갯수, 미션 내용을 불러올 예정이며
보상과 버튼은
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이벤트들 위쪽에 코드를 써두면 골드 초기화면이 출력될 것 같다. 하지만 문제가 있다.
각 버튼들을 눌렀더니 기존 데이터에 새로운 데이터가 덧씌워져서 그런지 버튼 두개가 동시에 눌리는 모습이다.
+초기화를 해야할 것 같은데 방법을 잘 모르겠다.