티스토리 뷰

* UIShop 상점 시스템 중 아이템을 구입하는 기능을 구현했다.

먼저 유저가 상점을 이용하려면 어떤 데이터가 있어야하는지 먼저 고민 해야했다.

유저의 현재 골드 보유량, 아이템 마다 정해진 가격(등급에 따라 가격을 나눈 후 데이터 테이블을 만들어놨다)이

먼저 필요했다.

그 후 상점에서 아이템을 구매하였다면  "유저의 현재 보유 금액 - 아이템의 가격" 을 다시 유저의 현재 보유 금액에 저장해야했다. 인포를 관리하기 위해   "PossessionAmount_info" 데이터 테이블을 만들었다. 유저가 보유할 수 있는 재화의 종류는 2가지 뿐임으로 (int)Gold, (int)Ether 만 정의해 놓았다. 

 아이템에 가격에 대한 Data는 테이블은 현재 레벨 기획 단계에서 좀 더 수정 할 부분이 있어서

 미리 만들어 놓은 EquipmentFactory에서 아이템의 가격을 직접 정해주고 만들어주었다.

info들을 관리하기 위하여 InfoManager를 싱글톤으로 만들고 어디서든 info에 접근 가능하게 만들었다

상점이용에서 InfoManager가 해줘야 하는 역할은 "유저의 보유 금액 - 구매하려는 아이템의 가격"을

저장하고(직렬화) 상점 스크립트에서 값을 받아 구매 가능여부를 체크했다

 

UIShopGrid에서는 InfoManager에서 받은 유저의 현재 재화 info 로 유저가 클릭한 아이템의 가격과

비교(현재 금액 > 아이템 가격)하여 거래 가능 여부를 체크했다.

가능 하다면 구매 버튼 활성, 버튼 알파값 1f, // 불가능 하다면 구매 버튼 비활성, 버튼 알파값 0.5f

구매 한 후 해당 아이템을 중복 구매 불가능하게끔 Cell의 컴포넌트 버튼을 비활성화 하고

아이콘과 프레임 알파값을 0.5f 로 바꿔줬다.

 

*UIShopGrid

using JetBrains.Annotations;
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

public class UIShopGrid : MonoBehaviour
{
    public enum eShopType //성소, 던전
    {
        Sanctuary=9, //Cell 9 food O
        Dungeon=5 //Cell 5 food X
    }

    public UIShopPopup uIShopPopup;
    public Transform equipmentContent;
    public Transform foodContent;
    private ShopFactory shopFactory;
    private bool isGoldEnough;
    public EquipmentCell clickedCell;
    public List<EquipmentCell> SanctuaryEquipmentCells;
    //SanctuaryAction
    //public System.Action onCreatSanctuaryShop;
    //public System.Action onCreatDungeonShop;
    //public System.Action onCreatFoodShop;

    public void Init()    
    {
        this.SanctuaryEquipmentCells= new List<EquipmentCell>();
        this.isGoldEnough = true;
        this.shopFactory = this.GetComponent<ShopFactory>();
        //this.ClickedCellOn();
        this.uIShopPopup.Init();

        this.shopFactory.onUIPopupActive = () => {
            this.uIShopPopup.gameObject.SetActive(true);
            this.PopupDetail();
            this.PopupDetailFrameColor();
            this.PopupDetailIcon();
            this.CheckCurrentGold();
        };
        this.uIShopPopup.onBuyItem = () => {
            if (this.isGoldEnough) AcceptBuyItem();
        };
    }

    public void SanctuaryShopCell()
    {
        this.shopFactory.CreatShopSword("Wood", this.equipmentContent);
        this.shopFactory.CreatShopAxe("Iron", this.equipmentContent);
        this.shopFactory.CreatShopArrow("Gold", this.equipmentContent);
        this.shopFactory.CreatShopWand("Diamond", this.equipmentContent);
        this.shopFactory.CreatShopSword("Wood", this.equipmentContent);
        this.shopFactory.CreatShopArrow("Diamond", this.equipmentContent);
        this.shopFactory.CreatShopWand("Gold", this.equipmentContent);
        this.shopFactory.CreatShopAxe("Iron", this.equipmentContent);
        this.shopFactory.CreatShopSword("Wood", this.equipmentContent);



    }
    public void DungeonShopCell()
    {
        this.shopFactory.CreatShopSword("Wood", this.equipmentContent);
        this.shopFactory.CreatShopArrow("Diamond", this.equipmentContent);
        this.shopFactory.CreatShopAxe("Iron", this.equipmentContent);
        this.shopFactory.CreatShopWand("Gold", this.equipmentContent);
        this.shopFactory.CreatShopAxe("Wood", this.equipmentContent);
    }

    public void FoodCell()
    {
        //Test
        this.shopFactory.CreatShopFood("Iron", this.foodContent);
        this.shopFactory.CreatShopFood("Gold", this.foodContent);
    }

   
    private void PopupDetail()
    {
        this.clickedCell = EventSystem.current.currentSelectedGameObject.GetComponent<EquipmentCell>(); //click된 오브잭트의 인스턴스 정보를 가져옴

        this.uIShopPopup.txtNameDetail.text = clickedCell.equipmentCellname;
        this.uIShopPopup.txtPowerStatDetail.text = $"공격력 : {clickedCell.powerStat}";
        this.uIShopPopup.txtCriticalHitAmountDetail.text = $"치명타공격력 : {clickedCell.criticalHitAmount.ToString()}";
        this.uIShopPopup.txtCriticalHitChanceDetail.text = $"치명타확률 : {clickedCell.criticalHitChance.ToString()}";
        this.uIShopPopup.txtFireRateStatDetail.text = $"공격속도 : {clickedCell.fireRateStat.ToString()}";
        this.uIShopPopup.txtRecoveryAmount.text = $"체력 : {clickedCell.recoveryAmount.ToString()}개 회복"; // C# 문자열 보간
        this.uIShopPopup.txtPriceDetail.text = $"{clickedCell.itemPrice.ToString()+"/"+ InfoManager.instance.possessionAmountInfo.goldAmount}";
    }
    private void PopupDetailFrameColor()
    {
        this.clickedCell = EventSystem.current.currentSelectedGameObject.GetComponent<EquipmentCell>();
        var color = clickedCell.transform.GetChild(0).GetComponent<Image>().color;
        this.uIShopPopup.frame.color = color;
    }
    private void PopupDetailIcon() 
    {
        this.clickedCell = EventSystem.current.currentSelectedGameObject.GetComponent<EquipmentCell>();
        var sprite = clickedCell.transform.GetChild(1).GetComponent<Image>().sprite;
        this.uIShopPopup.imgItem.sprite = sprite;
    }

    /// <summary>
    /// 유저의 현재 금액과 클릭한 아이템의 가격 비교
    /// 구매 버튼 활성/비활성
    /// 버튼 알파값 0.5/1
    /// </summary>
    private void CheckCurrentGold()
    {
        if(InfoManager.instance.possessionAmountInfo.goldAmount > this.clickedCell.itemPrice)
        {
            Debug.Log("거래가능");
            this.uIShopPopup.btnSelect.enabled = true;
            this.isGoldEnough = true;
            this.ButtonAlphaUp();
        }
        else
        {
            Debug.Log("거래불가");
            this.uIShopPopup.btnSelect.enabled = false;
            this.isGoldEnough = false;
            this.ButtonAlphaDown();

        }
    }

    /// <summary>
    /// 거래 수락, InfoManager에서 유저의 금액 차감하고 save
    /// </summary>
    private void AcceptBuyItem()
    {
        Debug.Log("<Color=green>AcceptBuy</Color>");
        InfoManager.instance.DecreasePossessionGoods(this.clickedCell.itemPrice);
        this.ClickedCellOff();
    }
    private void ButtonAlphaUp()
    {
        var img = this.uIShopPopup.btnSelect.transform.GetChild(0).GetComponent<Image>();
        Color color = img.color;
        color.a = 1f;
        img.color = color;
    }
    private void ButtonAlphaDown()
    {
        var img = this.uIShopPopup.btnSelect.transform.GetChild(0).GetComponent<Image>();
        Color color = img.color;
        color.a = 0.5f;
        img.color = color;
    }

    /// <summary>
    /// 중복 구입 방지
    /// 구매 했다면(AcceptBuyItem) Cell 활성화
    /// 프레임, 아이콘 알파값 1
    /// Init에서 초기화 필수
    /// </summary>
    private void CellActive()
    {
        this.clickedCell.gameObject.GetComponent<Button>().enabled = true;
        var frame = this.clickedCell.gameObject.transform.GetChild(0).GetComponent<Image>();
        var icon = this.clickedCell.gameObject.transform.GetChild(1).GetComponent<Image>();
        Color colorFrame = frame.color;
        Color colorIcon = icon.color;
        colorFrame.a = 1f;
        colorIcon.a = 1f;
        frame.color = colorFrame;
        icon.color = colorIcon;
    }
    private void ClickedCellOff()
    {
        this.clickedCell.gameObject.GetComponent<Button>().enabled = false;
        var frame = this.clickedCell.gameObject.transform.GetChild(0).GetComponent<Image>();
        var icon = this.clickedCell.gameObject.transform.GetChild(1).GetComponent<Image>();
        Color colorFrame = frame.color;
        Color colorIcon = icon.color;
        colorFrame.a = 0.5f;
        colorIcon.a = 0.5f;
        frame.color = colorFrame;
        icon.color = colorIcon;
    }
    
}

# 단순한 기능 구현이 아닌 팀 프로잭트임으로 생각할게 아주 많았다. 상점 UI 를 맡고 하다 보니 인벤토리UI와 

직접적으로 연관이 있는게 많았다. 유저의 저장시점이 언제인지 , 어떤 데이터를 저장해야하고 어떤 데이터를 저장하지 말아야할지(장르가 로그라이크 이다 보니 던전 안에서 재화정보, 구매 아이템은 저장하지 않는다)도 고민할 부분이 아주 많았다. 아직 좀더 추가해야하는 기능들과 수정할 부분들이 많다. 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/07   »
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
글 보관함