내일배움캠프 41일차 TIL <Unity ATM 만들기 2일차> 06/05

정광훈(Unity_9기)·2025년 6월 5일

TIL (Today I Learned)

목록 보기
51/110
post-thumbnail

<오늘 한 일>

json으로 데이터를 저장하고 다시 실행하면 저장값을 불러오는 작업을 했다.
게임에 적용은 처음이다 보니 실제로 구성하는데 어려움을 겪었다.

<발생한 문제>

의도한 것은 json 파일에 데이터가 없으면 인스펙터에서 할당한
초기값을 불러오는 것이었는데 이름이 비어있고 현금이 비어있는 상태로 나왔다.

public class GameManager : MonoBehaviour
{
    // 유저 데이터 저장/로드할 실제 파일 경로
    private string path;

    void Awake() // 초기화
    {
        Instance = this;

        path = Path.Combine(Application.persistentDataPath, "UserData.json");

        LoadUserData(); // 저장된 데이터 불러옴
        Refresh(); // UI 업데이트
    }

    public void Refresh() // UI 업데이트
    {
        nameText.text = userData.Name;
        cashText.text = string.Format("{0:N0}", userData.Cash);
        balanceText.text = string.Format("Balance   {0:N0}", userData.Balance);

        SaveUserData(); // UI가 업데이트 되면 업데이트된 데이터 값을 저장
    }

    #region json으로 저장

    public void SaveUserData() // 유저 데이터 저장
    {
        // 첫 번째 인자는 "Key"라는 저장 공간이고 "Key"의 이름에 따라 저장된 값을 불러온다.
        // 두 번째 인자는 저장할 데이터를 입력한다.
        PlayerPrefs.SetString("Name", userData.Name);
        PlayerPrefs.SetInt("Balance", userData.Balance);
        PlayerPrefs.SetInt("Cash", userData.Cash);
        // userData 인자를 Json 문자열로 변환
        // Formatting.Indented 가독성을 높이기 위해 들여쓰기를 해줌
        string jsonSave = JsonConvert.SerializeObject(userData, Formatting.Indented);

        PlayerPrefs.Save(); // 위의 내용들을 저장
        File.WriteAllText(path, jsonSave);
    }

    public void LoadUserData() // 유저 데이터 불러오기
    {
        // "Key"의 이름에 맞는 저장된 값을 불러온다.
        // 저장된 값이 없을 경우 두 번째 인자를 기본값으로 불러온다.
        userData.Name = PlayerPrefs.GetString("Name", "");
        userData.Balance = PlayerPrefs.GetInt("Balance", 0);
        userData.Cash = PlayerPrefs.GetInt("Cash", 0);
        string json = File.ReadAllText(path); // json 문자열을 읽어옴
        UserData jsonLoad = JsonConvert.DeserializeObject<UserData>(json);

        Refresh();
        // 불러온 데이터를 GameManager의 userData에 할당
        userData.Name = jsonLoad.Name;
        userData.Balance = jsonLoad.Balance;
        userData.Cash = jsonLoad.Cash;

        if (userData == null) 
        {
            userData = new UserData("", 0, 0);
        }
    }

    #endregion
}

일단 코드가 잘못되어 있다.
json을 게임에 처음 적용해 보고 기존 데이터를 읽어오는 것은 배웠지만
내가 파일을 만들어 데이터를 저장하고 그걸 다시 출력하는 것은 처음이었다.

<수정된 부분>

[1. SaveUserData()]

PlayerPrefs.SetString("Name", userData.Name);
PlayerPrefs.SetInt("Balance", userData.Balance);
PlayerPrefs.SetInt("Cash", userData.Cash);
PlayerPrefs.Save();
데이터를 저장하는 이 부분들은

string jsonSave = JsonConvert.SerializeObject(userData, Formatting.Indented);
File.WriteAllText(path, jsonSave);
이 두 줄과 똑같은 내용이다.
json형식으로 데이터를 저장한 것이다.

결국 똑같은 내용을 2번 반복한 셈.

[2. LoadUserData()]

userData.Name = PlayerPrefs.GetString("Name", "");
userData.Balance = PlayerPrefs.GetInt("Balance", 0);
userData.Cash = PlayerPrefs.GetInt("Cash", 0);
데이터를 불러오는 이 부분도 마찬가지로

string json = File.ReadAllText(path);
UserData jsonLoad = JsonConvert.DeserializeObject(json);
이 두 줄과 같은 내용인데 json 형식으로 데이터를 불러오는 것이다.

이것도 똑같은 내용을 2번 반복한 셈.

물론 PlayerPrefs는 레지스트리에 저장하고 불러오는 것이고
json은 별도의 json파일에 기록했다가 불러오는 식이라 다르기는 하다.

전체적으로 보면 서로 다른 곳에 똑같은 내용을 저장하고 있었다.

이 메서드는 게임 시작하면 처음에 데이터만 불러오면 되기 때문에
Refresh();는 필요없다.

Awake()에서 마지막에 UI 업데이트를 하기 위해 Refresh()가 있다.

그리고 json 파일은 {}포함 아무 것도 작성되어있어야 null 상태이기 때문에

기본값, 초기값이 적용되어 json에 저장이 되고 게임에도 적용이 된다.


<전체 코드>

using System.IO;
using Newtonsoft.Json;
using UnityEngine;
using TMPro;

public class GameManager : MonoBehaviour
{
    public static GameManager Instance { get; private set; }

    public UserData userData;

    [Header("텍스트UI 인스펙터에 연결")] [SerializeField]
    private TextMeshProUGUI nameText; // 유저 이름 출력 텍스트

    [SerializeField] private TextMeshProUGUI balanceText; // 통장 잔액 출력 텍스트
    [SerializeField] private TextMeshProUGUI cashText; // 현금 잔액 출력 텍스트

    public GameObject panel; // 잔액부족 판넬

    private string path; // 유저 데이터 저장/로드할 파일 경로

    void Awake() // 초기화
    {
        Instance = this;
        
        // persistentDataPath: 읽기 쓰기 가능한 저장 경로
        // Combine(저장경로, 생성할 파일 이름);
        path = Path.Combine(Application.persistentDataPath, "UserData.json");

        LoadUserData(); // 저장된 데이터 불러옴
        Refresh(); // UI 업데이트
    }

    #region 기능구현

    public void DepositCash(int amount) // 입금 - 버튼에 연결
    {
        if (userData.Cash - amount >= 0)
        {
            userData.Cash -= amount;
            userData.Balance += amount;
        }
        else
        {
            panel.SetActive(true);
        }

        Refresh();
    }

    public void withdrawalCash(int amount) // 출금 - 버튼에 연결
    {
        if (userData.Balance - amount >= 0)
        {
            userData.Balance -= amount;
            userData.Cash += amount;
        }
        else
        {
            panel.SetActive(true);
        }

        Refresh();
    }

    public void Refresh() // UI 업데이트
    {
        nameText.text = userData.Name;
        cashText.text = string.Format("{0:N0}", userData.Cash);
        balanceText.text = string.Format("Balance      {0:N0}", userData.Balance);

        SaveUserData();
    }

    #endregion

    #region json으로 저장

    public void SaveUserData() // 유저 데이터 저장
    {
        // userData 인자를 Json형식의 문자열로 변환 -> 직렬화
        // Formatting.Indented 가독성을 높이기 위해 들여쓰기를 해줌 
        string jsonSave = JsonConvert.SerializeObject(userData, Formatting.Indented);

        // path 경로에 파일이 없으면 jsonSave내용으로 생성하고, 파일이 있으면 내용을 덮어쓴다.
        File.WriteAllText(path, jsonSave);
    }

    public void LoadUserData() // 유저 데이터 불러오기
    {
        if (File.Exists(path)) // 경로에 파일이 존재하면
        {
            // 경로에 있는 파일의 모든 텍스트 내용을 읽어옴 -> 문자열 변수에 저장
            string json = File.ReadAllText(path);
            // json 형식의 문자열을 C# 객체(UserData 타입)로 변환 -> 역직렬화
            UserData jsonLoad = JsonConvert.DeserializeObject<UserData>(json);

            if (jsonLoad != null) // 제이슨에 저장된 데이터 값이 있다면
            {
                // 불러온 데이터를 userData에 할당
                userData.Name = jsonLoad.Name;
                userData.Balance = jsonLoad.Balance;
                userData.Cash = jsonLoad.Cash;
            }
        }
        
        if (userData == null) // 저장된 데이터가 없다면
        {
            // 기본값으로 할당
            userData = new UserData("", 0, 0);  
        }
    }

C:/Users/poker/AppData/LocalLow/DefaultCompany/ATM/UserData.json에
json 파일이 생기고 데이터가 저장된 것을 확인할 수 있다.

0개의 댓글