내일배움캠프 24일차

박나연·2025년 5월 12일

내배캠

목록 보기
24/69

2D 팀 프로젝트 진행중(UI 연결 작업)

오늘의 키워드 : 나...아트팀?

주말까지 작업을 좀 진행해서 해놓은게 많다. 일단 점수구현은 저번에 한걸로 됐고 주말에 UI에 쓸 이미지들을 제작했는데 오늘 주로 한 것은 버튼 이벤트 연결이다. 솔직히 버튼 이벤트 연결은 어렵지 않아서 딱히 트러블 슈팅할 것도 없어 오늘은 새로 작성한 스크립트에 대해서만 설명하고 마무리하려 한다. 원래 ScoreManagerGod Mode에서 직접적으로 게임을 클리어 처리 할 수 있었는데 이제 실제로 연동해야 해서 그 밑작업도 했다. (사실 연동까지 다 했는데 GameManager로 기능을 따로 빼야 한다고 해서...내일 다시 작업해야 한다...어렵진 않지만 귀찮다 흑흑)

ScoreUI.cs 의 포맷지정자 사용

화면에 목표시간까지 출력하고, 전에는 시간이 초만 보였는데 (60초가 넘어가면 1분 1초가 아니라 61초로 표시되는 등) 분, 초가 표시되게 수정하였다.

    public void InitializeTotals(int fireTotal, int iceTotal, int targetTime)
    {
        ........
        
        int tm = targetTime / 60;
        int ts = targetTime % 60;
        targetTimeText.text = $"목표 시간: {tm:D2}:{ts:D2}";
    }

D(Decimal)은 정수 값을 10진수 문자열로 포맷한다. 여기서 사용한 D2는 최소 두자리로 표현하되, 한 자리일 경우 앞에 0을 채움을 말한다.(3.ToString("D2") -> "03"
D계열은 정수 전용 포맷 지정자이므로 정수형에서 쓸 수 있기 때문에 int를 쓰도록 하자. 만약 실수에 쓰고 싶다면 F2 같은 부동소수점 전용 지정자를 사용.

StageUIController.cs

캔버스에 붙여 게임 흐름에 필요한 UI들을 관리한다.

    [Header("등급 표시용 UI")]
    [SerializeField] private Image gradeImage;
    [SerializeField] private Sprite[] gradeSprites;// A,B,C 

    [Header("조건 체크 아이콘")]
    [SerializeField] private Image timeCheckIcon;
    [SerializeField] private Image coinCheckIcon;
    [SerializeField] private Sprite checkSprite;         
    [SerializeField] private Sprite crossSprite;


    public struct RankResult
    {
        public GRADE Grade;       // A, B, C
        public bool TimeSuccess;  // 시간 조건 달성 여부
        public bool CoinSuccess;  // 코인 조건 달성 여부

        public RankResult(GRADE grade, bool timeSuccess, bool coinSuccess)
        {
            Grade = grade;
            TimeSuccess = timeSuccess;
            CoinSuccess = coinSuccess;
        }
    }

    //스테이지 클리어 후 등급 결정 UI
    public void ShowClearUI(RankResult result)
    {
        clearUI.SetActive(true);
        gradeImage.sprite = gradeSprites[(int)result.Grade];
        timeCheckIcon.sprite = result.TimeSuccess ? checkSprite : crossSprite;
        coinCheckIcon.sprite = result.CoinSuccess ? checkSprite : crossSprite;
        Time.timeScale = 0f;
    }

RankResult구조체를 만들어 등급과 두 개의 성공 조건(시간, 코인)을 하나로 묶어 UI쪽으로 간편하게 넘길 수 있도록 한다.

  • gradeSprites[(int)result.Grade]
    만약 A등급이면 index 0 이미지를, B라면 index 1이미지. C등급이면 index 2이미지를 가져와 보여준다.

  • 조건 아이콘
    result.TimeSuccesstruecheckSprite가, 아니면 crossSprite가 보이게 한다. 원작 게임도 이렇게 하길래 따라해보았다.

이로인해 추가된 코드는 ScoreManger에서 다음과 같다.

    public void Rank()
    {
        //제한 시간을 넘기지 않으면 false로 넘어옴. !가 붙었으므로 true임
        bool timeOK = !timeTracker.isTimeExceeded;
        //모든 파이어스타 먹으면 true
        bool fireOK = fireCollected == fireTotal;
        //모든 아이스스타 먹으면 true
        bool iceOK = iceCollected == iceTotal;
      
        (등급 결정 코드..)
        
        //추가된 코드
        var rankResult = new StageUIController.RankResult(result, timeOK, fireOK && iceOK);
        stageUI.ShowClearUI(rankResult);
    }

마무리하며

오늘은 UI작업을 많이 해서 크게 어렵진 않았지만 어떻게 구조를 짜야 좋을까에 대한 고민을 좀 했다. 종이에 좀 끄적이다 보니 확실히 정리가 잘 되는 느낌이었다.

내일 할 일

내일은 GameManager에 게임종료, 게임 클리어 ui를 연결하고 esc 기능을 넣으려 한다. 그 작업이 다 끝나면 코딩과는 상관없는 타이틀 로고와 아이콘들을 그릴 예정이다. 예전에도 ui를 했었는데 지금도 느끼지만 난 그런 ui만드는 것에 재능이 없는 것 같다... 아트팀이 괜히 있는게 아니다. 저 작업들이 끝나면 게임 클리어 ui에 애니메이션도 연결하려 한다. 아마 여기까지 완료하면 내가 맡은 일은 내일 모두 완료된다. 빨리 끝내고 발표 ppt 작성 좀 도와주고 개인 공부를 좀 하고 싶다.

0개의 댓글