내일배움캠프

내일배움캠프: 유니티 JsonUtility을 활용한 데이터 저장 및 불러오기

pracumj 2024. 11. 1. 21:25

JSON 간단 개념

 

JsonUtility를 사용해보자

유니티 엔진은 json을 활용해 데이터를 저장하고 불러오는 작업을 손쉽게 할 수 있도록 JsonUtility 를 제공하고 있다.

JsonUtility는 사용자가 Json 형식으로 데이터를 다루는 것을 편리하게 할 수 있게 해준다. 

JsonUtility 사용법

1.   JSON 데이터에 저장할 변수

-유니티에서는 구조화된 Json의 개념을 중심으로 json 직렬화 기능을 설계 했다고 한다.  덕분에 JsonUtility를 통해 클래스나 구조체 형태로 데이터를 쉽게 JSON으로 직렬화하고 역직렬화가 가능하다. 

예를 들어, 플레이어의 데이터를 저장하려면 PlayerData라는 클래스를 만들고, 그 안에 이름,스탯 등의 속성을 정의 해주면 된다.

[System.Serializable]
public class PlayerData
{
    public string playerName;
    public int level;
    public float maxHp;
    public float maxStamina;
}

 

해당 코드는 PlayerData 클래스 안에 JSON에 저장될 변수를 정의한 코드이다. 즉, JSON에 저장할 데이터를 담기 위해 PlayerData라는 클래스를 만들어 준 것이다. 여기에 [System.Serializable](직렬화) 속성을 사용해 클래스 필드를 정의하면, 이 데이터가 JSON 형식으로 쉽게 직렬화될 수 있다. [System.Serializable]를 사용하지 않는다면 JSON으로 직렬화가 불가능하다.

 

2.  인스턴스 직렬화 방법(데이터 저장)

PlayerData player = new PlayerData();
player.playerName = "내배캠";
player.level = 10;
player.maxHp = 100f;
player.maxStamina = 70f;


// JSON으로 직렬화
string json = JsonUtility.ToJson(player, true);

// 파일에 저장 (기존 내용 덮어쓰기)
File.WriteAllText(filePath, json);

// 파일에 내용 추가 (기존 내용 뒤에 이어쓰기)
File.AppendAllText(filePath, json);

 

JsonUtility.ToJson을 사용하여 인스턴스를 JSON 포맷으로 직렬화,  t true 옵션은 각 데이터 항목에 들여쓰기를 적용할지 여부를 결정하며  true 옵션을 사용하지 않으면 JSON이 한 줄로 압축되어 저장 돼 내용을 확인하기 불편할 수 있다. 

File.WriteAllText는 파일에 문자열을 저장하는 메서드로, 지정된 경로에 파일이 이미 있으면 해당 파일을 덮어쓰고, 파일이 없으면 새 파일을 생성하여 저장한다. 내용을 이어쓰고 싶으면 File.AppendAllText를 사용하면 된다.

 

3.  Json 파일 읽기 

// persistentDataPath: 플랫폼 간 경로 차이를 자동으로 처리
// JSON 파일을 숨겨서 안전하게 저장할 수 있는 경로
string filePath = Application.persistentDataPath + "/playerData.json";

// dataPath: 개발 환경에서 JSON 파일을 쉽게 확인하고 수정 가능
// 빌드된 게임에서는 읽기 전용으로 사용, 저장 기능을 빌드에서 사용할 시 문제가 생길 수 있음
string filePath = Application.dataPath + "/playerData.json";

데이터를 저장하거나 읽어올 JSON 파일의 경로를 설정, Application.persistentDataPath가 아닌 DataPath를 사용하면 빌드시 문제가 생길 확률이 높다.  DataPath는 개발 환경에서 데이터를 확인하거나 수정하기에 적합하다.

4.  Json 역직렬화(데이터 불러오기)

        // 파일이 존재하면 JSON 데이터를 읽어와서 객체로 변환
        string json = File.ReadAllText(filePath);
        PlayerData data = JsonUtility.FromJson<PlayerData>(json);

파일 경로에서 JSON 데이터를 읽어 객체로 변환해주는 과정, File.ReadAllText로 파일을 읽고, JsonUtility.FromJson으로 객체로 변환해줌. 

 

5. 예외처리 (방어코드)

//파일이 존재하면 TRUE값 반환 
if (File.Exists(filePath))
{
    // 파일이 존재할 경우 처리 로직
}
else
{
    // 파일이 없을 경우 예외 처리 로직
}

파일의 존재 여부를 확인하여 파일이 없을 때 처리 로직을 추가

위 5가지 방법을 잘 조합하면 기본적인 데이터 저장 및 불러오기 구현이 가능 해진다. 

 

참고링크:https://docs.unity3d.com/kr/560/Manual/JSONSerialization.html

 

배열, 리스트, 딕셔너리의 역직렬화

유니티에서 제공하는 JsonUtility 는 배열 ,리스트 ,딕셔너리 와 같은 복잡한 컬렉션 타입의 역직렬화를 직접적으로 지원하지 않는다. 그렇다고해서 해당 데이터들을 불러오고 사용할 수 없는 것은 아니다. 컬렉션 타입의 데이터를 JSON으로 저장하고 읽어오려면 컬렉션을 담을 컨테이너 클래스를 활용해 주면 된다.

 

컨테이너 활용 예시 코드 

[System.Serializable]
public class ListDataContainer
{
    public List<PlayerData> data; // 직렬화 및 역직렬화할 리스트

    public ListDataContainer(List<PlayerData> data)
    {
        this.data = data;
    }
}

 

PlayerData 클래스 안에 JSON에 저장하기 위한 컬렉션 타입의 변수를 정의, [System.Serializable] 속성을 사용하여 클래스가 직렬화될 수 있도록 설정하면, 이 데이터는 JSON 형식으로 쉽게 직렬화할 수 있다.

 

왜 컨테이너 클래스가 필요할까?

앞서 말했듯이 Unity의 JsonUtility는 복잡한 컬렉션 타입의 역직렬화를 직접적으로 지원하지 않는다. 객체 안에 컬렉션 타입이 포함된 구조는 문제 없이 잘 처리하지만, 컬렉션 타입만으로 이루어진 JSON 데이터는 직접 역직렬화가 불가능하다. 이를 해결하기위해 컨테이너 클래스를 새로 만들어 컬렉션 타입을 감싸주는 것이다.