[내일 배움 캠프] 1주차 - 카드만들기 - RankingSystem

하얀요니콘·2025년 7월 2일

내일 배움 캠프 첫 과제는 카드 뒤집기를 만드는 것이다. Ranking판을 만드는 작업을 하였고, Ranking판의 로직에 맞게 작업을 하였다.

RankingManager과 PlayerPref을 활용한 데이터 저장

RankingManager을 만들고, PlayerPref을 사용하여 데이터를 저장한다.
아쉽지만 PlayerPref에서 어레이 형태로 저장되지 않아, 다음과 같이 GenKey를 짠 후, 작업을 하였다.

    public string GenKey(int index)
    {
        return ScoreTemplate + index.ToString();
    }

이코드로, 이름을 입력하는대신, 함수에 인덱스를 넣어 값을 저장하거나 찾으면 된다.

반면 스코어를 ClearScene에서 가져 올 때 값들을 비교 해 주기위해, 다음과 같은 코드를 사용한다.

public bool CheckHigh(float score)
{
    for (int i = 0; i < RankingMaxSize; i++)
    {
        if (!PlayerPrefs.HasKey(GenKey(i)) || score < PlayerPrefs.GetFloat(GenKey(i)))
            return true;
    }
    return false;
}

이는 점수를 받고, 만약 키에 저장된 값이 없거나, 해당 점수가 저장된 값보다 작다면 true를, 아니면 랭킹 권 밖이므로 false를 반환한다.

이제 이 값을 순서대로 정리 해 주기 위하여, 다음과 같이 활용한다.

    public void AddScore(float score)
    {
        int size = 0;
        while(PlayerPrefs.HasKey(GenKey(size)) && size < RankingMaxSize)
            size++;
        int last_index;
        if (size < RankingMaxSize)
        {
            PlayerPrefs.SetFloat(GenKey(size), score);
            last_index = size;
        }
        else
        {
            PlayerPrefs.SetFloat(GenKey(RankingMaxSize - 1), score);
            last_index = RankingMaxSize - 1;
        }
        while (last_index > 0)
        {
            float f = PlayerPrefs.GetFloat(GenKey(last_index-1));
            float b = PlayerPrefs.GetFloat(GenKey(last_index));
            if (b < f)
            {
                PlayerPrefs.SetFloat(GenKey(last_index - 1), b);
                PlayerPrefs.SetFloat(GenKey(last_index), f);
                last_index--;
            }
            else
                break;
        }
    }

for문에서 무한루프 돌아가서 잠시 고생했었다.
아쉽게도 PlayerPref이 array를 저장 못하기 때문에, 지금 저장된 값들 수를 직접 확인 해 주어야 한다. 지금 와서 생각해보면 사이즈를 저장 해도 됬을 것 같지만...

그 사이즈에 따라 제일 뒤 (빈칸일수도 있고, 아닐 수도 있다.) 에 받은 스코어를 넣어준다.
그 후 인덱스를 줄여나가며, 전값과 뒷값을 비교하여 현재 값이 더 작다면, 바꿔 준 뒤 한칸 씩 앞으로 나가면 된다. 버블 정렬(bubble sort)의 일종이지만, 실은 데이터가 적으며, 앞 배열이 이미 정렬되어 있어 이 예시에서는 효율적이다. 만약 크다면 자리를 전부 찾았으므로, 멈춰주면 된다.

이제 RankingBoard라는 스크립트에 해당 값을 찾아, 해당 위치에 넣어주면 된다.

RectTransform

스크립트에서 RectTransform의 사이즈를 변경하고 싶을 경우가 있을것이다. 하지만 RectTransform은 선택한 프리셋에 따라 입력하는 방식이 다르므로, 이를 해결할 방법을 찾아보았다.
나는 가로값은 고정, 세로 값은 변경을 해 주고 싶었다. 해당 코드를 보자.

RectTransform rt = canvas.GetComponent<RectTransform>();
rt.sizeDelta = new Vector2 (rt.sizeDelta.x, 100);

RectTransform은 transform의 localscale이 아닌 sizeDelta라는것을 가져온다. 이것을 활용하여, 실제 크기를 각 상황에 대입시켜 작업 해 줄 수 있다.

UI 파티클

추가적으로 하고 싶어 파티클 작업을 해 주었다. 랭킹판에 기록이 있다면, 폭죽을 쏴 주는 방식이다.

파티클을 있는 에셋으로 겨우 겨우 제작했다. 컴포넌트가 많아서 알아낸 것 위주로만 적자.

  • Duration : 실제 애니메이션이 얼마나 진행되는지이다.
  • Looping : 당연하게, 반복을 할지를 정한다
  • Start Lifetime : 시작 후 얼마후에 파티클이 사라질 지 결정한다.
  • Start Color : 시작 색상이다. 물론 단색도 있지만, 옆에 드롭다운 눌러주면 다양한 설정이 있다.
  • GravitySource : 2D환경이니 파티클을 2D physics로 바꿔주자.
  • Emitter Velocity Mode : 충돌 판정이 필요 없으니, rigidbody가 아닌 Transform을 사용한다.
  • StopAction : 끝나면 할 행동이다. Destroy를 사용하여 삭제하였다.
  • Emission : 무작위 생성을 하려면 이미션이 들어간다.
  • Shape : 파티클 입자가 아니라, 파티클 입자가 시작할 위치, 범위 설정이다. 2D환경이라 Circle로 작업한다.
  • Color Over Lifetime : 끝나면서 색상이 투명해지는 연출을 위해 사용했다. 시간에 따라 색상이 어떻게 될지 정한다.
  • Size Over Lifetime : 마찬가지이다. 다만 이는 그래프를 사용한다.
  • Renderer : 이게 입자이다.

파티클을 만들고, 생성을 해 주려 했는데, UI가 위에 가려서, 파티클이 보이지 않는 문제가 발생하였다.
찾아보니 해결방법 중 하나는 다음과 같다.

  1. 카메라를 하나 더 만들어준다. (FX용 카메라)
  2. FX용 카메라 레이어를 UI로, Render Type을 Overlay로 설정해 주도록 하자.
  3. 이제 Main Camera에 가서, Stack 부분에 FX용 카메라를 추가해준다.
  4. 기존에 UI캔버스가 UI에 오버레이 되면 안된다. Canvas의 Render모드를 Screen-Spcae-Camera로 설정, 및 Render Camera를 Main카메라로 해준다. 모르니 Order in Layer도 확인하자.
  5. FX카메라 자식으로 이제 파티클이든 뭐든 넣어준다. 마찬가지로 Screen-Space-Camera로 변경해주고, Render Camera는 FX카메라로 설정 해 준다. Order in Layer은 기존 UI 캔버스의 레이어 넘버보다 키워 앞으로 옮겨준다.

이러면 Main Camera위 UI카메라가 UI카메라 자식에 있는 내용들을 송출해 준다. 참고로 Camera생성시 Audio Listener이 생기므로, 하나만 남기고 다 지워주다 (Main거 남기고 지우면 된다.)

이렇게 해서 파티클 생성을 해 보았다. 어찌저찌 하다보니 되긴 했는데, 다음 시간에 플레이 영상이 생긴다면, 올려드리겠다.

profile
코딩공부용

0개의 댓글