[24.03.18]Unity - UI(Vending Machine)

손지·2024년 3월 18일
0

Unity

목록 보기
30/44


Button, Text를 추가하고

UI는 계산을 해선 안된다.

그리고 숫자 추가하고 자리를 잡아준다.

(업로드는 내일)

버튼 위치만 고치면 된다.

UIProductinfo.cs

using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;

public class UIProductInfo : MonoBehaviour
{
    public enum EProduct
    {
        Coke, Coffee, Milk, Kkang, Homerun
    }

    [System.Serializable]
    public struct ProductInfo
    {
        public EProduct name;
        public int price;
        public int stock;

        public bool HaveStock()
        {
            return stock > 0;
        }

        public void Print()
        {
            Debug.Log(name + " / " + price + " 원 / " + stock + "개");
        }
    }

    public static string EnumToString(EProduct _name)
    {
        switch (_name)
        {
            case EProduct.Coke: return "콜라";
            case EProduct.Coffee: return "커피";
            case EProduct.Milk: return "밀크";
            case EProduct.Kkang: return "깡";
            case EProduct.Homerun: return "홈런볼";
        }
        return string.Empty;
    }
}

UVVendingMachine.cs

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

public class UIVendingMachine : MonoBehaviour
{
    [SerializeField]
    private GameObject productButtonPrefab = null;
    //[SerializeField]
    //private string name = null;

    //[SerializeField]
    //private UIProductInfo.ProductInfo[]
    //    productInfos = null;

    private RectTransform imgBackTr = null;
    private TextMeshProUGUI textName = null;

    private List<UIProductButton> productBtnList = new List<UIProductButton>();

    private int vmIndex = -1;


    private void Awake()
    {
        Image imgBack =
            GetComponentInChildren<Image>();
        imgBackTr = imgBack.GetComponent<RectTransform>();
        textName =
            GetComponentInChildren<TextMeshProUGUI>();
    }

    // 게으른 초기화(Lazy Initialization)
    public void Init(VMDatabase.VMInfo _vmInfo, UIProductButton.OnClickDelegate _onClickCallback)
    {
        vmIndex = _vmInfo.vmIndex;
        //textName.text = name;
        textName.text = _vmInfo.vmName;

        BuildButtons(_vmInfo.productInfos, _onClickCallback);
    }

    public void TurnOnOff(bool _on)
    {
        gameObject.SetActive(_on);
    }

    private void BuildButtons(
        UIProductInfo.ProductInfo[] _productInfos, UIProductButton.OnClickDelegate _onClickCallback)
    {
        // odd, even
        bool odd = _productInfos.Length % 2 != 0 ? true : false;
        Vector3 startPos = Vector3.zero;
        float offsetW = 0f;
        float offsetH = 0f;
        CalcStartPosAndOffset(
            _productInfos,
            out startPos,
            out offsetW,
            out offsetH);

        for (int i = 0; i < _productInfos.Length; ++i)
        {
            GameObject go =
                Instantiate(
                    productButtonPrefab,
                    transform);

            UIProductButton productBtn =
                go.GetComponent<UIProductButton>();
            productBtn.Init(vmIndex, i, _productInfos[i]);

            productBtn.SetLocalPosition(
                new Vector3(
                    startPos.x + (offsetW * (i % 3)),
                    startPos.y - (offsetH * (i / 3)),
                    0f
                    ));

            productBtn.SetOnClickDelegate(_onClickCallback);

            productBtnList.Add(productBtn);
        }
    }

    private void CalcStartPosAndOffset(
        UIProductInfo.ProductInfo[] _productInfos,
        out Vector3 _startPos,
        out float _offsetW,
        out float _offsetH)
    {
        float imgW = imgBackTr.sizeDelta.x;
        int divCntW = (_productInfos.Length % 2) + 3;
        float offsetW = imgW / divCntW;
        float startX = -(imgW * 0.5f) + offsetW;

        float imgH = imgBackTr.sizeDelta.y;
        int divCntH = ((_productInfos.Length + 2) / 3);
        float offsetH = imgH / divCntH;
        float startY = (imgH * 0.5f) - offsetH;

        _startPos = new Vector3(startX, startY, 0f);
        _offsetW = offsetW;
        _offsetH = offsetH;
    }

    public void UpdateStock(int _btnIdx, int _stock)
    {
        productBtnList[_btnIdx].UpdateStock(_stock);
    }

    public bool EqualIndex(int _vmIdx)
    {
        return vmIndex == _vmIdx;
    }
}

VMDatabase.cs

using System.Collections;
using System.Collections.Generic;
using System.IO.IsolatedStorage;
using UnityEngine;

public class VMDatabase : MonoBehaviour
{
    [System.Serializable]public struct VMInfo
    {
        public int vmIndex;
        public string vmName;
        public UIProductInfo.ProductInfo[] productInfos;
        public VMInfo(int _vmIdx, string _vmName, UIProductInfo.ProductInfo[] _productInfos) 
        {
            vmIndex = _vmIdx;
            vmName = _vmName;
            productInfos = _productInfos;
        }

        public static VMInfo NULL()
        {
            return new VMInfo(-1, string.Empty, null);
        }

        public bool isNull()
        {
            return vmIndex == -1;
        }
    }

    [SerializeField] private VMInfo[] vmInfos = null;


    public VMInfo[] FindAll()
    {
        return vmInfos;
    }
    public VMInfo FindWithIndex(int _vmIndex)
    {
        foreach (VMInfo info in vmInfos)
        {
            if (info.vmIndex == _vmIndex)
            {
                return info;
            }
        }
        //Null 객체
        return VMInfo.NULL();
    }

    public bool FindProductInfo(int _vmIdx, int _btnIdx, ref UIProductInfo.ProductInfo _productinfo)
    {
        foreach(VMInfo info in vmInfos)
        {
            if(info.vmIndex == _vmIdx)
            {
                if(_btnIdx >= 0 && _btnIdx < info.productInfos.Length)
                {
                    _productinfo = info.productInfos[_btnIdx];
                    return true;
                }
            }
        }
        return false;
    }

    //Increment / Decrement
    public void StockDecrement(int _vmIdx, int _btnIdx)
    {
        foreach(VMInfo info in vmInfos)
        {
            if(info.vmIndex == _vmIdx)
            {
                --info.productInfos[_btnIdx].stock;
            }
        }
    }
}

VMPlayer.cs

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

public class VMPlayer : MonoBehaviour
{
    private int money = 100000;

    public int Money { get { return money; } }
    public bool CanPay(int _price)
    {
        return money > _price;
    }
    public void Pay(int _price)
    {
        money -= _price;
    }
}

UIProductButton.cs

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

public class UIProductButton : MonoBehaviour
{
    private enum EIndex { Name, Price, Stock }

    public delegate void OnClickDelegate(int _vmIdx, int _btnIdx);
    private OnClickDelegate onClickCallback = null;

    private Button btn = null;
    private TextMeshProUGUI[] texts = null;
    private RectTransform rectTr = null;
    private int vmIndex = -1;
    private int btnIndex = -1;
    private void Awake()
    {
        btn = GetComponentInChildren<Button>();
        texts = GetComponentsInChildren<TextMeshProUGUI>();
        rectTr = GetComponent<RectTransform>();
    }
    public void Init(int _vmIdx, int _btnidx, UIProductInfo.ProductInfo _info)
    {
        vmIndex = _vmIdx;
        btnIndex = _btnidx;
        texts[(int)EIndex.Name].text = UIProductInfo.EnumToString(_info.name);
        texts[(int)EIndex.Price].text = _info.price.ToString() + "원";
        texts[(int)EIndex.Stock].text = _info.stock.ToString()  + "개";
    }

    public void SetOnClickDelegate(OnClickDelegate _callback)
    {
        onClickCallback = _callback;
        btn.onClick.AddListener(() => 
        { 
            onClickCallback?.Invoke(vmIndex, btnIndex); 
        });
    }

    public void SetLocalPosition(Vector3 _localPos) 
    {
        rectTr.localPosition = _localPos;
    }

    public void UpdateStock(int _stock)
    {
        texts[(int)EIndex.Stock].text = _stock.ToString() + "개";
    }
}

UIVMButton.cs

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

public class UIVMButton : MonoBehaviour
{
    public delegate void OnClickDelegate(int _idx);
    private int index = -1;
    private Button btn = null;



    private void Awake()
    {
        btn = GetComponent<Button>();
    }

    public void SetOnClickCallBack(int _idx , OnClickDelegate _onClickCallback)
    {
        btn.onClick.AddListener(
            () =>
            {
                _onClickCallback(_idx);
            });
    }
}

UIVMHolder.cs

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

public class UIVMHolder : MonoBehaviour
{
    private UIVendingMachine[] vms = null;
    private UIVendingMachine prevVm = null;

    private void Awake()
    {
        vms = GetComponentsInChildren<UIVendingMachine>();
    }


    public void Init(VMDatabase.VMInfo[] _vmInfos, UIProductButton.OnClickDelegate _onClickCallback)
    {
        for(int i = 0; i < _vmInfos.Length; ++i)
        {
            vms[i].Init(_vmInfos[i], _onClickCallback);
        }
        TurnOffAll();
    }

    private void TurnOffAll()
    {
        foreach(UIVendingMachine vm in vms)
        {
            vm.TurnOnOff(false);
        }
    }

    public void TurnOn(int _idx)
    {
        if(prevVm != null)
        {
            prevVm.TurnOnOff(false);
        }

        vms[_idx].TurnOnOff(true);

        prevVm = vms[_idx];
    }

    public void UpdateStock(int _vmIdx, int _btnIdx, int _stock)
    {
        foreach(UIVendingMachine vm in vms)
        {
            if (vm.EqualIndex(_vmIdx))
            {
                vm.UpdateStock(_btnIdx, _stock);
            }
        }
    }
}

UIVMButtonHolder.cs

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

public class UIVMButtonHolder : MonoBehaviour
{
    
    private UIVMButton[] vmBtns = null;

    private void Awake()
    {
        vmBtns = GetComponentsInChildren<UIVMButton>();
    }

    public void SetOnClickCallback(UIVMButton.OnClickDelegate _onClickCallback)
    {
        for(int i = 0; i < vmBtns.Length; ++i)
        {
            vmBtns[i].SetOnClickCallBack(i, _onClickCallback);
        }
    }
}

VMSimulator.cs

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

public class VMSimulator : MonoBehaviour
{
    [SerializeField] private VMPlayer vmPlayer = null;
    [SerializeField] private UIVMButtonHolder vmBtnHolder = null;
    [SerializeField] private UIVMHolder vmHolder = null;
    [SerializeField] private VMDatabase vmDB = null;
    [SerializeField] private UIWallet wallet = null;

    private void Start()
    {
        vmHolder.Init(vmDB.FindAll(), ProductButtonCallback);
        vmBtnHolder.SetOnClickCallback(VMButtonCallback);

        wallet.SetMoney(vmPlayer.Money);
    }

    private void VMButtonCallback(int _vmIdx)
    {
        vmHolder.TurnOn(_vmIdx);
    }

    private void ProductButtonCallback(int _vmIdx, int _btnIdx)
    {
        UIProductInfo.ProductInfo info = new UIProductInfo.ProductInfo();
        if(vmDB.FindProductInfo(_vmIdx, _btnIdx, ref info))
        {
            if (info.HaveStock())
            {
                if (vmPlayer.CanPay(info.price))
                {
                    vmPlayer.Pay(info.price);
                    wallet.SetMoney(vmPlayer.Money);
                    info.Print();

                    //데이터베이스 재고 줄이기
                    vmDB.StockDecrement(_vmIdx, _btnIdx);
                    //갱신된 DB 정보 가져오기
                    if(vmDB.FindProductInfo(_vmIdx, _btnIdx, ref info))
                    {
                        //해당 버튼 정보 갱신
                        vmHolder.UpdateStock(_vmIdx, _btnIdx, info.stock);
                    }
                    //vmDB.FindProductInfo
                    
                }
            }
            info.Print();
        }
    }
}

하이라키

profile
게임 개발자가 될사람

0개의 댓글

관련 채용 정보