EasyCastleUNITY

유니티 GUI 3 (Stage UI) 본문

유니티 심화

유니티 GUI 3 (Stage UI)

EasyCastleT 2023. 9. 6. 14:55

하는 역할들

1. 실행하면 1번 스테이지 제외하면 클릭불가능

2. 1번 스테이지 클릭하면 다음 스테이지 클릭이 가능해짐

3. 스테이지를 누르면 랜덤으로 별의 갯수가 정해지고 별 갯수만큼 보여줌

4. 오른쪽 위에 텍스트를 통해 별 갯수 총합을 보여줌 

5. 페이지 마지막 스테이지를 클릭하면, 다음 페이지로 넘어감

6. 5번과 상관없이 양 옆에 버튼으로도 페이지 전환 가능 

만든 UI 구조

UIMain이 가장 상위, 그 다음이 UIPageStage -> UIStageController -> UIStage

가장 밑인 UIStage 부터 게제

UIStage

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

public class Test04UIStage : MonoBehaviour
{
    public enum eState
    {
        Lock, Doing, Complete
    }
    [SerializeField] private TMP_Text[] arrTxtStageNum;

    [SerializeField] private GameObject[] arrStateGo; //0:lock, 1:doing 2:complete

    [SerializeField] private GameObject[] arrStarGo;

    private eState state = eState.Lock;

    public eState State
    {
        get { return state; }
        set { state = value; }
    }

    private Button button;
    private int stageNum;

    public int StageNum
    {
        get { return stageNum; }
    }

    public Button Button
    {
        get { return button; }
    }

    private int starCount;

    public int StarCount
    {
        get { return starCount; }
        set { starCount = value; }
    }
    public void Init(int stageNum)
    {
        this.button = this.GetComponent<Button>();
        this.stageNum = stageNum;
        this.SetRandomStarCount();
        foreach (var tmpText in this.arrTxtStageNum)
        {
            tmpText.text = stageNum.ToString();
        }
        if (stageNum == 1) this.ChangeState(eState.Doing);
        else this.ChangeState(eState.Lock);
        //this.ChangeState(state);
        this.OnStar(this.starCount);
    }

    public void ChangeState(eState state)
    {
        this.InActiveAll();

        this.state = state;
        int index = (int)this.state;
        this.arrStateGo[index].SetActive(true);
    }
    private void InActiveAll()
    {
        foreach (var go in this.arrStateGo)
        {
            go.SetActive(false);
        }
    }

    private void OnStar(int starCount)
    {
        foreach (var go in this.arrStarGo)
        {
            go.SetActive(false);
        }

        for (int i = 0; i < starCount; i++)
        {
            this.arrStarGo[i].SetActive(true);
        }
    }

    private void SetRandomStarCount()
    {
        this.starCount = Random.Range(0, 4); // 0~3
    }
}

UIStageController

인스펙터

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

public class Test04UIStageController : MonoBehaviour
{
    [SerializeField]
    private Test04UIStage[] arrUiStage;

    [SerializeField] private int onePagePerMaxStage; //1차 
    public int OnePagePerMaxStage
    {
        get { return this.onePagePerMaxStage; }
    }
    [SerializeField] private int wholeStages;
    public int WholeStages
    {
        get { return this.wholeStages; }
    }

    public System.Action onLastButtonClick;
    public System.Action onButtonClick;

    private int sumStarCount = 0;
    public int SumStarCount
    {
        get { return this.sumStarCount; }
    }

    public void Init()
    {
        this.OnStage(this.wholeStages);
        for(int i=0; i<arrUiStage.Length; i++)
        {
            int index = i;
            arrUiStage[i].Init(i + 1);
            arrUiStage[i].Button.onClick.AddListener(() => {
                if (arrUiStage[index].State != Test04UIStage.eState.Lock)
                {
                    arrUiStage[index].ChangeState(Test04UIStage.eState.Complete);
                    if (index + 1 < arrUiStage.Length) //에러 피하기 위함 
                        arrUiStage[index + 1].ChangeState(Test04UIStage.eState.Doing);
                    if( (index+1) % onePagePerMaxStage == 0)
                    {
                       this.onLastButtonClick();
                    }
                    this.sumStarCount += arrUiStage[index].StarCount; //스타 카운트 더하기 
                    this.onButtonClick();
                }
                else
                {
                    Debug.Log("클릭 불가능");
                }
            });
        }
    }

    private void OnStage(int maxStage)
    {
        //전부 다 끄기 
        foreach(var uiStage in this.arrUiStage)
        {
            uiStage.gameObject.SetActive(false);
        }
        //maxStage 값 만큼 키기 
        for(int i=0; i< maxStage; i++)
        {
            this.arrUiStage[i].gameObject.SetActive(true);
        }
    }
}

UIPageStage

page는 LayoutGroup

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

public class Test04UIPageStage : MonoBehaviour
{
    [SerializeField]
    private Test04UIStageController stageController;

    [SerializeField] private Button btnPrev;
    [SerializeField] private Button btnNext;

    [SerializeField] private GameObject[] pages;

    [SerializeField] private TMP_Text pageNumText;
    [SerializeField] private TMP_Text starCountText;

    private int maxPages;
    private int currentPageNum = 1;

    private int onePagePerMaxStage;
    private int wholeStages;

    private int sumStarCount;

    public void Init()
    {
        this.stageController.Init();
        this.onePagePerMaxStage = this.stageController.OnePagePerMaxStage;
        this.wholeStages = this.stageController.WholeStages;
        this.CalcPagesNum(this.onePagePerMaxStage,this.wholeStages);
        this.CallInfo();
        this.ToShowCurrentPageNum();
        this.ToShowCountStar();

        this.btnPrev.onClick.AddListener(() => {
            Debug.Log("이전 페이지로");
            if (this.currentPageNum != 1) this.currentPageNum--;
            else if (this.currentPageNum == 1) Debug.Log("현재 페이지가 1 페이지 입니다");
            this.PageChange();
            this.ToShowCurrentPageNum();
            CallCurrentPageInfo();
        });
        this.btnNext.onClick.AddListener(() => {
            Debug.Log("다음 페이지로");
            if (this.currentPageNum != this.maxPages) this.currentPageNum++;
            else if (this.currentPageNum == this.maxPages) Debug.Log("현재 페이지가 마지막 페이지입니다");
            this.PageChange();
            this.ToShowCurrentPageNum();
            CallCurrentPageInfo();
        });

        this.stageController.onLastButtonClick = () => {
            Debug.Log("다음 페이지로");
            this.currentPageNum++;
            if(this.currentPageNum <= this.maxPages)
            this.PageChange();
            else
            {
                this.currentPageNum = this.maxPages;
            }
            this.ToShowCurrentPageNum();
            CallCurrentPageInfo();
        };

        this.stageController.onButtonClick = () => {
            this.ToShowCountStar();
        };
    }
    //총 페이지 수 계산 
    private void CalcPagesNum(int maxStage, int wholeStage)
    {
        this.maxPages = Mathf.CeilToInt((float)wholeStage / maxStage); //반올림
        Debug.LogFormat("최대 페이지:{0}", this.maxPages);
    }

    //페이지 넘어갈 때마다 정보 보여줌 
    private void CallCurrentPageInfo()
    {
        int firstNum = (this.currentPageNum - 1) * this.onePagePerMaxStage + 1;
        int lastNum = this.currentPageNum * this.onePagePerMaxStage;
        Debug.LogFormat("총 스테이지:{0}", this.wholeStages);
        Debug.LogFormat("현재 페이지:{0}", this.currentPageNum);
        Debug.LogFormat("마지막 페이지:{0}", this.maxPages);
        Debug.LogFormat("스테이지 {0} ~ {1}", firstNum, lastNum);
    }

    //시작시 정보 보여줌 
    private void CallInfo()
    {
        Debug.LogFormat("총 스테이지:{0}", this.wholeStages);
        Debug.LogFormat("현재 페이지:{0}", this.currentPageNum);
        Debug.LogFormat("마지막 페이지:{0}", this.maxPages);
        Debug.LogFormat("스테이지 1~{0}", this.onePagePerMaxStage);
    }

    //현재 페이지 번호를 보여주는 메서드 
    private void ToShowCurrentPageNum()
    {
        this.pageNumText.text = string.Format("{0} / {1}",
            this.currentPageNum,this.maxPages);
    }

    private void PageChange()
    {
        foreach(var page in pages)
        {
            page.SetActive(false);
        }
        pages[this.currentPageNum-1].SetActive(true);
    }

    private void ToShowCountStar()
    {
        this.sumStarCount = this.stageController.SumStarCount;
        this.starCountText.text = string.Format("{0} / {1}", 
            this.sumStarCount,3*wholeStages);
    }
    
}

UIMain

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

public class Test04UIMain : MonoBehaviour
{
    [SerializeField] private Test04UIPageStage pageStage;
    private void Start()
    {
        this.pageStage.Init();
    }
}

'유니티 심화' 카테고리의 다른 글

골드 상점 GUI  (0) 2023.09.09
유니티 GUI (스크롤 뷰 및 셀) 및 데이터 연동  (0) 2023.09.07
유니티 GUI 2  (0) 2023.09.05
유니티 GUI  (0) 2023.09.04
Hero SHooter 개발일지 2  (0) 2023.09.03