내일배움캠프 Unity 4일차 TIL - Chapter1 미니프로젝트에 추가 기능 구현

Wooooo·2023년 11월 2일
0

내일배움캠프Unity

목록 보기
6/94

오늘의 키워드

오늘까지 제출해야하는 내일배움캠프 Chapter 1의 미니프로젝트가 있었다.
게임개발종합반 4주차 강의에서 진행한 카드게임을 따라서 만들면 되는 프로젝트다.
추가기능을 구현해도 된다고 해서 여태까지의 클리어타임 중에 가장 빠른 1~5위를 저장해두고, 게임오버 창에 띄워주는 기능을 구현했다.

베스트 클리어타임 저장 - List

베스트 클리어 타임을 저장할 List가 필요했다. 이 List는 다음의 규칙을 따른다.

  • 모든 카드쌍을 매칭하여 클리어했을 경우 List에 이번 판의 클리어타임을 추가
  • List에 새로운 값이 들어오면 오름차순으로 정렬
  • List의 크기가 5 이상이라면 크기가 5가 될 때 까지 뒤에서부터 하나씩 pop (가장 빠른 클리어타임 5개만 유지)
    public void AddBestTime()
    {
        bestTimes.Add(time);
        bestTimes = bestTimes.OrderBy(item => item).ToList();
        while (bestTimes.Count > 5)
            bestTimes.RemoveAt(bestTimes.Count - 1);
    }

PlayerPrefs를 이용해 List를 Save/Load

PlayerPrefs는 유니티에서 데이터를 플레이어의 로컬에 Save/Load 할 수 있게 해주는 기능이다.
string, int, float 3가지 자료형을 취급할 수 있으며, 저장할 땐 keyvalue가 한 쌍이다.
keystring타입이며, 변수명을 그대로 가져다 쓰는 등, 이게 어디에 쓰는 데이터인지 알아 볼 수 있게 해주는 것이 좋겠다.

근데 내가 취급할 데이터는 List<float>이다. 배열 데이터를 저장해야하는데 그런건 없다. 그래서 List<float>string으로 변환해서 저장하기로 했다. JSON처럼 말이다.

저장할 때는 List<float>의 값들을 string으로 변환하고, 원소 사이사이에 ',' 문자로 구분해준다.

ex) List의 원소가 { 1 2 3 4 5 } 라면, string "1,2,3,4,5"로 변환하여 저장.

    public void SaveBestTimes()
    {
        string key = "bestTimes";
        string value = "";
        for (int i = 0; i < bestTimes.Count; i++)
            value += bestTimes[i].ToString("N2") + ',';
        value = value.TrimEnd(',');
        PlayerPrefs.SetString(key, value);
        Debug.Log("save : " + key + ":" + value);
    }

불러올 때는 PlayerPrefs에서 받아온 string',' 문자로 split하고 float형으로 parsing하여 List로 들고 온다!

    public void LoadBestTimes()
    {
        List<float> res = new List<float>();
        string key = "bestTimes";
        string value = PlayerPrefs.GetString(key);
        Debug.Log("load : " + key + ":" + value);
        if (value.Length != 0)
        {
            var splits = value.Split(',');
            for (int i = 0; i < splits.Length; i++)
                res.Add(float.Parse(splits[i]));
            bestTimes = res;
        }
    }

UI에 표시

    void GameOver()
    {
        Time.timeScale = 0f;
        LoadBestTimes();
        if (time <= 30f)
            AddBestTime();
        SaveBestTimes();
        for (int i = 0; i < bestTimes.Count; i++)
            bestTimeTexts[i].text = bestTimes[i].ToString("N2");
        gameOverWindow.SetActive(true);
    }

게임이 끝나면, PlayerPrefs에서 데이터를 불러와서 List로 받는다. 이 List에 이번 판의 클리어 타임(클리어 못했다면 패스)을 추가하고 순위를 갱신한다.
갱신된 List를 다시 PlayerPrefs에 저장하고, GameOver 창에 순서대로 표시해준다. 이때, bestTimeTexts[i].text의 기본값은 아직 자리가 남은 순위권의 처리를 위해 "-"로 해줬다.

제대로 동작하는지 확인

테스트를 위해 리스트에 { 25.30, 28.88, 28.90, 29.70 } 4개를 넣어놓고 그대로 클리어 실패를 해봤다.

제대로 동작하는 것 같다. 다음 판은 리스트에 제대로 삽입/정렬이 되는지 확인하기 위해 클리어를 해봤다.

25.30초 만에 클리어했고 제대로 1위에 랭크됐다. 다음 판은 리스트가 제대로 크기 5를 유지하는지 확인하기 위해 클리어를 해봤다.

18.76초 만에 클리어했고 제대로 1위에 랭크됐다. 기존의 5위였던 29.70초는 순위권에서 쫓겨났고 제대로 동작하는 것을 확인했다.

마치며

처음에 배열 요소를 로컬에 저장한다고 생각했을 떄, 프로젝트에 JSON을 설치해야하나.... 싶었다.
구글링을 해보니 PlayerPrefsstring으로 변환해서 배열을 저장할 수 있다는 걸 보고 JSON 쓸 생각은 하면서 왜 이 생각은 못했지? 싶었다.
PlayerPrefs가 취급하는 자료형이 string, float, int뿐이라 string에는 문자열만 저장해야한다는 틀에 박힌 사고방식 때문인 것 같다.
유연한 사고를 해야겠다. 어떻게 해야 유연한 사고를 할 수 있을까 ,,

profile
game developer

0개의 댓글