본문 바로가기

Unity

유니티 - 게임 데이터 JSON으로 저장하기

반응형

 

유니티로 게임 제작 시 각종 데이터 정보를 Json으로 저장하는 방법에 대해 알아보겠습니다.

Json 저장은 유니티에서 기본 제공하는 JsonUtility을 사용 했습니다.

 

저장할 데이터 목록은 

public List<string> testDataA = new List<string>();
public List<int> testDataB = new List<int>();

public int gold;
public int power;

string 리스트 10개와 int 리스트 10개 그리고 플레이어의 골드 및 파워를 저장해 보겠습니다. 

 

public class GameManager : MonoBehaviour {
    public static GameManager instance;

    public List<string> testDataA = new List<string>();
    public List<int> testDataB = new List<int>();

    public int playerGold;
    public int playerPower;

    void Awake() {
        instance = this;
    }
}

우선 GameManager 클래스에 게임 진행에 필요한 데이터 정보를 관리하는 리스트 및 변수들이 있습니다.

Json에서 불러온 정보를 이쪽으로 저장하며 또는 데이터를 Json으로 저장하는 역할을 할 것입니다.

 

using System.IO;

[System.Serializable]
public class SaveData {
    public List<string> testDataA = new List<string>();
    public List<int> testDataB = new List<int>();

    public int gold;
    public int power;
}

public class DataManager : MonoBehaviour {
    string path;

    void Start() {
        path = Path.Combine(Application.dataPath, "database.json");
        JsonLoad();
    }

    public void JsonLoad() {
        SaveData saveData = new SaveData();

        if (!File.Exists(path)) {
            GameManager.instance.playerGold = 100;
            GameManager.instance.playerPower = 4;
            SaveData();
        } else {
            string loadJson = File.ReadAllText(path);
            saveData = JsonUtility.FromJson<SaveData>(loadJson);

            if (saveData != null) {
                for (int i = 0; i < saveData.testDataA.Count; i++) {
                    GameManager.instance.testDataA.Add(saveData.testDataA[i]);
                }
                for (int i = 0; i < saveData.testDataB.Count; i++) {
                    GameManager.instance.testDataB.Add(saveData.testDataB[i]);
                }
                GameManager.instance.playerGold = saveData.gold;
                GameManager.instance.playerPower = saveData.power;
            }
        }
    }

    public void JsonSave() {
        SaveData saveData = new SaveData();

        for (int i = 0; i < 10; i++) {
            saveData.testDataA.Add("테스트 데이터 no " + i);
        }

        for (int i = 0; i < 10; i++) {
            saveData.testDataB.Add(i);
        }

        saveData.gold = GameManager.instance.playerGold;
        saveData.power = GameManager.instance.playerPower;

        string json = JsonUtility.ToJson(saveData, true);
        
        File.WriteAllText(path, json);
    }
}

 

 

Json으로 저장하기 위한 코드입니다.

File을 사용하기 위해 using System.IO; 를 선언해 줍니다.

 

[System.Serializable]
public class SaveData {
    public List<string> testDataA = new List<string>();
    public List<int> testDataB = new List<int>();

    public int gold;
    public int power;
}

자료를 저장하기 전 GameManager의 데이터를 이곳으로 받아 직렬화를 해줍니다.

 

string path;

void Start() {
    path = Path.Combine(Application.dataPath, "database.json");
    JsonLoad();
}

json 파일이 저장될 위치를 path에 저장합니다.

 

path = Path.Combine(Application.dataPath, "database.json");

 

파일의 위치는 Assets 폴더에 저장되며 다른 곳에 저장하고 싶다면 폴더를 하나 만들어 위치를 지정해 주시면 됩니다.

Path.Combine(Application.dataPath + "/Data/", "database.json")

이렇게 하시면 Assets/Data 폴더에 저장이 되는 형식입니다.

만약 안드로이드용 게임이라면 

Path.Combine(Application.persistentDataPath, "database.json");

이렇게 변경해 주시면 됩니다.

LoadData() 게임을 시작하면 데이터를 불러와 UI 창에 정보를 대입시켜 줍니다.

LoadData()의 시작위치가 Start()가 아닌 Awake()에서 실행하면 UI가 화면 그려지기 전 데이터가 먼저 들어와 아직 활성화되기 전인 UI에 정보를 주려 하기 때문에 null 에러가 발생할 수 있습니다.

 

    public void JsonLoad() {
        SaveData saveData = new SaveData();

        if (!File.Exists(path)) {
            GameManager.instance.playerGold = 100;
            GameManager.instance.playerPower = 4;
            JsonSave();
        } else {
            string loadJson = File.ReadAllText(path);
            saveData = JsonUtility.FromJson<SaveData>(loadJson);

            if (saveData != null) {
                for (int i = 0; i < saveData.testDataA.Count; i++) {
                    GameManager.instance.testDataA.Add(saveData.testDataA[i]);
                }
                for (int i = 0; i < saveData.testDataB.Count; i++) {
                    GameManager.instance.testDataB.Add(saveData.testDataB[i]);
                }
                GameManager.instance.playerGold = saveData.gold;
                GameManager.instance.playerPower = saveData.power;
            }
        }
    }

 

if (!File.Exists(path)) {
   GameManager.instance.playerGold = 100;
   GameManager.instance.playerPower = 4;
   JsonSave();
}

JsonLoad를 실행했는데 Json 파일 없다면 이곳에서 처음 시작하는 데이터 정보를 만들어 Json파일을 만들어 줍니다.

 

string loadJson = File.ReadAllText(path);
saveData = JsonUtility.FromJson<SaveData>(loadJson);

Json 파일이 있다면 File.ReadAllText()로 불러와 string 형식의 loadJson에 담아 두며

JsonUtility를 사용하여 FromJson<SaveData>(loadJson) loadJson을 SaveData형식의 직렬화 모델로 변환해 줍니다.

이렇게 불러온 Json데이터를 이제 GameManager에 있는 리스트 및 변수에 저장해 주시면 됩니다.

 

if (saveData != null) {
    for (int i = 0; i < saveData.testDataA.Count; i++) {
        GameManager.instance.testDataA.Add(saveData.testDataA[i]);
    }
    for (int i = 0; i < saveData.testDataB.Count; i++) {
        GameManager.instance.testDataB.Add(saveData.testDataB[i]);
    }
    GameManager.instance.playerGold = saveData.gold;
    GameManager.instance.playerPower = saveData.power;
}

이런 식으로 saveData 내용을 리스트및 변수에 저장해 주시면 됩니다.

 

 

    public void JsonSave() {
        SaveData saveData = new SaveData();

        for (int i = 0; i < 10; i++) {
            saveData.testDataA.Add("테스트 데이터 no " + i);
        }

        for (int i = 0; i < 10; i++) {
            saveData.testDataB.Add(i);
        }

        saveData.gold = GameManager.instance.playerGold;
        saveData.power = GameManager.instance.playerPower;

        string json = JsonUtility.ToJson(saveData, true);
        
        File.WriteAllText(path, json);
    }

SaveData saveData = new SaveData(); 를

JsonSave() 안에 선언하지 않고 외부에 선언하면 같은 Json 데이터가 계속 쌓여 저장됩니다. 

{
    "testDataA": [
        "테스트 데이터 no 0",
        "테스트 데이터 no 1",
        "테스트 데이터 no 2",
        "테스트 데이터 no 3",
        "테스트 데이터 no 4",
        "테스트 데이터 no 5",
        "테스트 데이터 no 6",
        "테스트 데이터 no 7",
        "테스트 데이터 no 8",
        "테스트 데이터 no 9",
        "테스트 데이터 no 0",
        "테스트 데이터 no 1",
        "테스트 데이터 no 2",
        "테스트 데이터 no 3",
        "테스트 데이터 no 4",
        "테스트 데이터 no 5",
        "테스트 데이터 no 6",
        "테스트 데이터 no 7",
        "테스트 데이터 no 8",
        "테스트 데이터 no 9"
    ],
    "testDataB": [
        0,
        1,
        2,
        3,
        4,
        5,
        6,
        7,
        8,
        9,
        0,
        1,
        2,
        3,
        4,
        5,
        6,
        7,
        8,
        9
    ],
    "gold": 100,
    "power": 77
}

 

for (int i = 0; i < 10; i++) {
   saveData.testDataA.Add("테스트 데이터 no " + i);
}

for (int i = 0; i < 10; i++) {
   saveData.testDataB.Add(i);
}

saveData.gold = GameManager.instance.playerGold;
saveData.power = GameManager.instance.playerPower;

저장할 데이터를 saveData로 보내 직렬화를 시켜 줍니다.

 

string json = JsonUtility.ToJson(saveData, true);

직렬화된 saveData를 ToJson을 이용해 string json에 저장합니다.

ToJson(saveData)에서 true 옵션이 빠진다면 

 

{"testDataA":["테스트 데이터 no 0","테스트 데이터 no 1","테스트 데이터 no 2","테스트 데이터 no 3","테스트 데이터 no 4","테스트 데이터 no 5","테스트 데이터 no 6","테스트 데이터 no 7","테스트 데이터 no 8","테스트 데이터 no 9"],"testDataB":[0,1,2,3,4,5,6,7,8,9],"gold":100,"power":4}

이렇게 한 줄로만 저장됩니다. 

 

File.WriteAllText(path, json);

마지막으로 json 데이터를 파일로 저장해 주시면 끝!

 

이상으로 게임 정보를 Json으로 저장해 보았는데 게임에서 저장해야 될 변수가 많아지면 그 부분의 코드가 길어질 뿐

Json 저장과 불러오기는 딱 이것뿐입니다.

string path = Path.Combine(Application.dataPath, "database.json");

// 불러오기
string loadJson = File.ReadAllText(path);
saveData = JsonUtility.FromJson<SaveData>(loadJson);

// 저장하기
string json = JsonUtility.ToJson(saveData); 
File.WriteAllText(path, json);

참 저장하긴 전 데이터 직렬화도 잊지 마세요!!

반응형