EasyCastleUNITY

보석 상점 GUI 본문

유니티 심화

보석 상점 GUI

EasyCastleT 2023. 9. 9. 18:09

https://easycastleunity.tistory.com/150

 

골드 상점 GUI

정적 스크롤 뷰를 사용한 골드를 파는 상점 UI를 만들어 보려고 한다. 먼저 기본 바탕인 정적 스크롤 뷰를 만들고 그 안에 각각의 셀들을 만들려고 한다. scrollview에 Scroll Rect 컴포넌트 부여하고,

easycastleunity.tistory.com

이 포스트의 ScrollView 만드는 것과 동일하기에 ScrollView 만드는 부분은 생략한다. 

스크롤 뷰 정상작동 확인

이 다음에는 UIGemCell을 만든다. 

저번 포스트인 골드 상점에서 만든 UIGoldCell과 구성요소는 거의 같다. 

만든 UIGemCell

상품 이미지와 이름 텍스트, 수량 테스트, 가격 텍스트와 구매버튼으로 이루어져있다. 

프로젝트 구조

UIMain -> UIPageGemShop->UIGemScrollView -> UIGemCell 의 구조로 만들었다. 

데이터 테이블 작성

만든 json 파일

[
  {
    "id": "100",
    "name": "Tiny of Gem",
    "sprite_name": "set_icon_gem_0",
    "gem_amount": "180",
    "price": "1.99"
  },
  {
    "id": "101",
    "name": "Fistful of Gem",
    "sprite_name": "set_icon_gem_1",
    "gem_amount": "500",
    "price": "4.99"
  },
  {
    "id": "102",
    "name": "Pouch of Gem",
    "sprite_name": "set_icon_gem_2",
    "gem_amount": "1200",
    "price": "11.99"
  },
  {
    "id": "103",
    "name": "Box of Gem",
    "sprite_name": "set_icon_gem_3",
    "gem_amount": "2500",
    "price": "24.99"
  },
  {
    "id": "104",
    "name": "Chest of Gem",
    "sprite_name": "set_icon_gem_4",
    "gem_amount": "6500",
    "price": "59.99"
  },
  {
    "id": "105",
    "name": "Vault of Gem",
    "sprite_name": "set_icon_gem_5",
    "gem_amount": "14000",
    "price": "119.99"
  }
]

DataManager

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

public class DataManager 
{
    
    public static readonly DataManager instance = new DataManager(); //싱글톤 
    //상자 정보를 저장할 사전 
    private Dictionary<int, ChestData> chestDataDics = new Dictionary<int, ChestData>();
    //미션 정보를 저장할 사전
    private Dictionary<int, MissionData> missionDataDic = new Dictionary<int, MissionData>();
    //골드 정보를 저장할 사전 
    private Dictionary<int, GoldData> goldDataDic = new Dictionary<int, GoldData>();
    //젬 정보를 저장할 사전 
    private Dictionary<int, GemData> gemDataDic = new Dictionary<int, GemData>();
    //생성자
    private DataManager()
    {

    }

    public void LoadChestDatas()
    {
        TextAsset aseet = Resources.Load<TextAsset>("chest_data"); //json은 안 붙임

        //역직렬화
        ChestData[] chestDatas = JsonConvert.DeserializeObject<ChestData[]>(aseet.text);
        foreach(var chestData in chestDatas)
        {
            this.chestDataDics.Add(chestData.id, chestData);
        }
        Debug.Log("상자 로드 완료");
    }

    public void LoadMissionDatas()
    {
        TextAsset asset = Resources.Load<TextAsset>("mission_data");
        //역직렬화 
        MissionData[] missionDatas = JsonConvert.DeserializeObject<MissionData[]>(asset.text);
        //사전 등록
        foreach(var missionData in missionDatas)
        {
            this.missionDataDic.Add(missionData.id, missionData);
        }
        Debug.Log("미션 로드 완료");
    }

    public void LoadGoldDatas()
    {
        TextAsset asset = Resources.Load<TextAsset>("gold_data");
        //역직렬화
        GoldData[] goldDatas = JsonConvert.DeserializeObject<GoldData[]>(asset.text);
        //사전 등록
        foreach(var goldData in goldDatas)
        {
            this.goldDataDic.Add(goldData.id, goldData);
        }
        Debug.LogFormat("<color=yellow>Gold Count: {0}</color>",this.goldDataDic.Count);
        Debug.Log("골드 로드 완료");
    }

    public void LoadGemDatas()
    {
        TextAsset asset = Resources.Load<TextAsset>("gem_data");
        //역직렬화
        GemData[] gemDatas = JsonConvert.DeserializeObject<GemData[]>(asset.text);
        //사전 등록
        foreach(var gemData in gemDatas)
        {
            this.gemDataDic.Add(gemData.id, gemData);
        }
        Debug.LogFormat("<color=yellow>Gem Count: {0}</color>", this.gemDataDic.Count);
        Debug.Log("젬 로드 완료");
    }
    public List<ChestData> GetChestDatas()
    {
        return this.chestDataDics.Values.ToList();
    }

    public List<MissionData> GetMissionDatas()
    {
        return this.missionDataDic.Values.ToList();
    }

    public List<GoldData> GetGoldDatas()
    {
        return this.goldDataDic.Values.ToList();
    }

    public List<GemData> GetGemDatas()
    {
        return this.gemDataDic.Values.ToList();
    }
}

 

GemData -> 데이터 매핑 클래스 

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

public class GemData 
{
    //    id   name    sprite_name gem_amount  price
    //   int string       string     int       float

    public int id;
    public string name;
    public string sprite_name;
    public int gem_amount;
    public float price;

}

실행결과 및 스크립트

사용한 아틀라스

UIGemShopMain

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

public class UIGemShopMain : MonoBehaviour
{
    [SerializeField]
    private UIPageGemShop uiPageGemShop;

    private void Start()
    {
        DataManager.instance.LoadGemDatas();
        List<GemData> gemDatas = DataManager.instance.GetGemDatas();
        this.uiPageGemShop.Init(gemDatas);
    }
}

UIPageGemShop

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

public class UIPageGemShop : MonoBehaviour
{
    [SerializeField]
    private UIGemScrollview gemScrollview;

    public void Init(List<GemData> gemDatas)
    {
        foreach(GemData data in gemDatas)
        {
            Debug.LogFormat("<color=yellow>{0},{1},{2},{3},{4}</color>",
                data.id,data.name,data.sprite_name,data.gem_amount,data.price);
            this.gemScrollview.Init(data);
        }
    }
}

UIGemScrollview

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

public class UIGemScrollview : MonoBehaviour
{
    [SerializeField] private GameObject gemCellPrefab;
    [SerializeField] private SpriteAtlas gemAtlas;
    public void Init(GemData data)
    {
        GameObject context = GameObject.FindGameObjectWithTag("Content");
        GameObject go = Instantiate(this.gemCellPrefab, context.transform);
        UIGemCell gem = go.GetComponent<UIGemCell>();
        this.SetGemCellInfo(gem, data);
        gem.Init();
        gem.onBuyButtonClick = () => {
            Debug.LogFormat("<color=yellow>젬 양:{0}, 가격:{1}</color>",
                    data.gem_amount, data.price);
        };
    }

    private void SetGemCellInfo(UIGemCell cell, GemData data)
    {
        cell.Id = data.id;
        cell.Name = data.name;
        cell.Sprite_name = data.sprite_name;
        cell.Gem_amount = data.gem_amount;
        cell.GemSprite = this.gemAtlas.GetSprite(data.sprite_name);
        cell.Price = data.price;
    }
}

UIGemCell

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

public class UIGemCell : MonoBehaviour
{
    public System.Action onBuyButtonClick;
    #region Data
    private int id;
    private new string name;
    private string sprite_name;
    private int gem_amount;
    private float price;
    private Sprite gemSprite;

    public int Id { get => id; set => id = value; }
    public string Name { get => name; set => name = value; }
    public string Sprite_name { get => sprite_name; set => sprite_name = value; }
    public int Gem_amount { get => gem_amount; set => gem_amount = value; }
    public float Price { get => price; set => price = value; }
    public Sprite GemSprite { get => gemSprite; set => gemSprite = value; }
    #endregion
    [SerializeField] private TMP_Text txtName;
    [SerializeField] private TMP_Text txtGemAmount;
    [SerializeField] private TMP_Text txtPrice;
    [SerializeField] private Image gemImage;
    [SerializeField] private Button btnBuy;
    public void Init()
    {
        this.txtName.text = this.name;
        this.txtGemAmount.text = this.gem_amount.ToString();
        this.txtPrice.text = string.Format("US ${0}", this.price);
        this.SetImage(this.gemImage, this.gemSprite);

        this.btnBuy.onClick.AddListener(() => {
            this.onBuyButtonClick();
            Debug.LogFormat("젬 양:{0}, 가격:{1}", this.gem_amount, this.price);
        });
    }

    private void SetImage(Image image, Sprite sprite)
    {
        image.sprite = sprite;
        image.SetNativeSize();
    }
}

이번에도 이미지가 나오는 결과가 안 좋다는 것을 알 수 있다. 

따라서 다시 위치 정보를 json 데이터로 만들어 수정해보겠다. 

새로운 데이터 테이블

새로운 Json 

[
  {
    "id": "100",
    "name": "Tiny of Gem",
    "sprite_name": "set_icon_gem_0",
    "gem_amount": "180",
    "price": "1.99",
    "posX": "0",
    "posY": "83"
  },
  {
    "id": "101",
    "name": "Fistful of Gem",
    "sprite_name": "set_icon_gem_1",
    "gem_amount": "500",
    "price": "4.99",
    "posX": "4",
    "posY": "109"
  },
  {
    "id": "102",
    "name": "Pouch of Gem",
    "sprite_name": "set_icon_gem_2",
    "gem_amount": "1200",
    "price": "11.99",
    "posX": "-20",
    "posY": "41"
  },
  {
    "id": "103",
    "name": "Box of Gem",
    "sprite_name": "set_icon_gem_3",
    "gem_amount": "2500",
    "price": "24.99",
    "posX": "0",
    "posY": "54"
  },
  {
    "id": "104",
    "name": "Chest of Gem",
    "sprite_name": "set_icon_gem_4",
    "gem_amount": "6500",
    "price": "59.99",
    "posX": "3",
    "posY": "15"
  },
  {
    "id": "105",
    "name": "Vault of Gem",
    "sprite_name": "set_icon_gem_5",
    "gem_amount": "14000",
    "price": "119.99",
    "posX": "-18",
    "posY": "20"
  }
]

이후로 코드를 고치고 다시 실행해보았다. 

정상적으로 나오는 이미지

최종실행영상

버튼을 누르면 가격과 구입하는 젬의 양을 출력한다.