์ง๋ ๊ธ์์ JSON ํ์์ ๋ํด ์์๋ณด์๋ค.
์ด๋ฒ์๋ ๋ณธ๊ฒฉ์ ์ผ๋ก JSON ํ์ผ์ ์ด์ฉํด์ ๊ฒ์ ์ ์ฅ ๊ธฐ๋ฅ์ ๋ง๋ค์ด๋ณด์. ์ฝ๋๋ง ์ฐธ๊ณ ํ๊ณ ์ถ์ผ๋ฉด ๋งจ ๋ฐ์ผ๋ก ๋ด๋ฆฌ๋ฉด ๋๋ค.
์ผ๋จ ์ ์ฅ๊ธฐ๋ฅ์ ๊ตฌํํ๊ธฐ ์ ์, ์ฐ๋ฆฌ๋ ๋ฌด์จ ๋ฐ์ดํฐ๋ฅผ JSON์ผ๋ก ์ ์ฅํด์ผํ ๊น? ๋ฐ์ดํฐ์ผ ์ฌ๋ฌ๊ฐ์ง๊ฐ ์์ง๋ง ๋ณดํต ๋ค์๊ณผ ๊ฐ์ ์์๊ฐ ์์ ๊ฒ์ด๋ค.
ํ๋ ์ด์ด์ ์ ๋ณด, ๊ฒ์ ์ค์ , ํ์ฌ๊น์ง์ ์งํ ์ํฉ...
์ด์ ์ฐ๋ฆฐ ์ด๋ฐ ๋ฐ์ดํฐ๋ค์ JSON ํ์์ผ๋ก ์ ์ฅํด์ผํ๋ค. ์์ ๊ธ์์ ๋์๋ ๊ฒ์ฒ๋ผ, JSON ํ์ผ์ ํค์ ๊ฐ ์์ ํํ๋ก ์ด๋ค์ ธ ์๋ค๋๊ฑธ ๊ธฐ์ตํ์. ์์ ์์์์ ์ธ๊ธ๋ ๋ฐ์ดํฐ๋ฅผ JSON์ผ๋ก ๋ํ๋ธ๋ค๋ฉด ๋ค์๊ณผ ๊ฐ์ด ๋ํ๋ผ ์ ์๋ค.
{
"player": {
"name": "Player1",
"level": 5,
"items": ["sword", "shield"],
"currentStage": {
"id": 3,
"name": "Forest of Shadows",
"progress": 45
},
"clearedStages": [
{
"id": 1,
"name": "Plains of Beginning",
"time": "00:12:34"
},
{
"id": 2,
"name": "Cave of Echoes",
"time": "00:24:56"
}
]
},
"settings": {
"volume": 70,
"difficulty": "normal"
}
}
์ด์ธ์๋ ๋ค์ํ ๋ฐ์ดํฐ๋ค์ด ํฌํจ๋ ์๋ ์๋ค.
์, ์ด๋ป๊ฒ ๋ฐ์ดํฐ๋ฅผ JSON ํ์์ผ๋ก ์ ์ฅํ ์ง๋ ๊ณ ๋ฏผํด๋ดค์ผ๋ ์ด์ JSON์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํด๋ณด์.
๋จผ์ ์ฐ๋ฆฌ๋ ํ์ผ์ ์ ์ฅํ ์์น๋ฅผ ์ ํด์ผํ๋ค. ํ์ผ์ ์๋ฌด๋ฐ ์์น์๋ค ์ ์ฅํด๋์ผ๋ฉด ๋์ค์ ์ฐพ๊ธฐ๋ ํ๋ค๊ณ ๊ด๋ฆฌํ๊ธฐ๋ ๋ฒ๊ฒ๋ค.
์ด๋ด ๋๋ฅผ ์ํด ์ ๋ํฐ์์ ์ ๊ณตํ๋ ๊ฒฝ๋ก์ธ Application.persistentDataPath ๊ฐ ์๋ค.
์ด ํ๋กํผํฐ๋ ๊ฐ ํ๋ซํผ ๋ณ๋ก ์ ์ ํ ๋๋ ํฐ๋ฆฌ๋ฅผ ์ ๊ณตํ๊ธฐ์ ๋ฒ๊ฑฐ๋กญ๊ฒ ๊ฒฝ๋ก๋ฅผ ์ผ์ผํ ์ ํด์ค ํ์๊ฐ ์๋ค.
C:\Users\<์ฌ์ฉ์์ด๋ฆ>\AppData\LocalLow\<ํ์ฌ์ด๋ฆ>\<ํ๋ก์ ํธ์ด๋ฆ>~/Library/Application Support/<ํ์ฌ์ด๋ฆ>/<ํ๋ก์ ํธ์ด๋ฆ>/data/data/<ํจํค์ง์ด๋ฆ>/files<์ฑ ์๋๋ฐ์ค ๋๋ ํ ๋ฆฌ>/Documents๋ง์ฝ ์ค์ ๊ฒฝ๋ก๊ฐ ๋ง๋์ง ํ์ธํ๋ ค๋ฉด ์๋์ ์ฝ๋๋ฅผ ์คํ์์ผ๋ณด๋ฉด ๋๋ค.
Debug.Log("Save Path: " + Application.persistentDataPath);
๊ทธ๋ฆฌ๊ณ ์ฌ์ฉ์๊ฐ ์ฑ์ ์ญ์ ํ์ง ์๋ ํ ๋ฐ์ดํฐ๋ ์๊ตฌ์ ์ผ๋ก ์ ์ง๋๊ธฐ์ ์ฌ์ฉ์์ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๊ธฐ์ ์ ํฉํ๋ค.
๋ค๋ง ํ์ผ ๋ณ์กฐ๊ฐ ๊ฐ๋ฅํ๊ธฐ์, ์ค์ํ๊ฑฐ๋ ๊ฐ์ธ์ ์ธ ์ ๋ณด๋ฅผ ์ํธํํ์ง ์์ ์ํ๋ก Application.persistentDataPath ์ ์ ์ฅํ๋ ๊ฒ์ ์ถ์ฒ๋์ง ์๋๋ค.
Application ํด๋์ค์ ํ๋กํผํฐ๋ฅผ ์ดํด๋ณด๋ฉด, ๊ฒฝ๋ก์ ๋ํ ์ฌ๋ฌ ํ๋กํผํฐ๋ฅผ ์ฐพ์ ์ ์๋ค.
์ด์ค์์ ๋ช ๊ฐ์ง๋ง ์ดํด๋ณด๋ฉด
Application.dataPathAsset ํด๋ ์์ ๋ด์ฉ์ ๋น๋ ์, ํน์ ํ์์ผ๋ก ํจํค์ง ๋๊ธฐ์ ๊ฒฝ๋ก ๊ธฐ๋ฐ ์ ๊ทผ์ด ๋ถ๊ฐ๋ฅํ๋ค.
๋ค๋ง Resources ํด๋์ ์ ๊ทผํ ๋๋ ์๋ ์์์ฒ๋ผ ๊ฒฝ๋ก ๊ธฐ๋ฐ์ด ์๋ Resources.Load ๋ฅผ ์ฌ์ฉํด ์ ๊ทผํ ์ ์๋ค.
๊ทธ๋ฆฌ๊ณ ๋ฐ์์ ์๊ธฐํ StreamingAssets ํด๋์ ๊ฒฝ์ฐ์๋ง ์์ธ์ ์ผ๋ก ๊ฒฝ๋ก ๊ธฐ๋ฐ ์ ๊ทผ์ด ๊ฐ๋ฅํ๋ค.
// Resources/myFile.txt ํ์ผ์ ์ฝ๊ธฐ
TextAsset textAsset = Resources.Load<TextAsset>("myFile"); // ํ์ฅ์ ์ ์ธ
Application.streamingAssetsPath์ด ์ธ์๋ ์์์ ์ธ ์บ์ ํ์ผ์ ์ ์ฅํ๋ ๊ฒฝ๋ก์ธ, Application.temporaryCachePath
์ฝ์ ๋ก๊ทธ์ ๋ํ ๊ฒฝ๋ก๋ฅผ ๋ฐํํ๋,
Application.consoleLogPath ๊ฐ ์๋ค.
(Serialization)์ ์ด์ ๊ฒ์ ๋ฐ์ดํฐ๋ฅผ JSON์ผ๋ก ๋ณํํด๋ณด์. UNITY๋ ์ด๋ฐ ์ง๋ ฌํ ๊ณผ์ ์ ์ํด JsonUtility๋ฅผ ๊ธฐ๋ณธ์ ์ผ๋ก ์ ๊ณตํ๋ฉฐ, ์ด ์ธ์ ๋ค์ํ ๊ธฐ๋ฅ์ด ํ์ํ ๊ฒฝ์ฐ Newtonsoft์ JSON ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ ์๋ ์๋ค.
์ฐ๋ฆฌ๋ ์ ๋ํฐ์์ ๊ธฐ๋ณธ์ ์ผ๋ก ์ ๊ณตํ๋ JsonUtility๋ฅผ ํตํด์ ์ง๋ ฌํ๋ฅผ ํด๋ณด์.
๋จผ์ ๊ฒ์ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํด์ฃผ๋ ํด๋์ค๋ฅผ ๋ง๋ค์.
[System.Serializable] // ์ง๋ ฌํ๋ฅผ ํ๊ฒ ๋ค๋ ์ดํธ๋ฆฌ๋ทฐํธ(Attribute)
public class PlayerData
{
public string name;
public int level;
public string[] items;
}
์ด์ SaveManager ์คํฌ๋ฆฝํธ๋ฅผ ๋ง๋ค์ด์ฃผ๊ณ ๋ค์๊ณผ ๊ฐ์ด ์ ์ด์ฃผ์.
using System.IO;
using UnityEngine;
public class SaveManager : MonoBehaviour
{
public void SaveData(PlayerData data)
{
// ๊ฒฝ๋ก ์ค์
string path = Path.Combine(Application.persistentDataPath, "playerData.json");
// JSON์ผ๋ก ์ง๋ ฌํ
string jsonData = JsonUtility.ToJson(data, true); // true๋ ์ฝ๊ธฐ ์ฝ๊ฒ ํฌ๋งทํ
Debug.Log("JSON Data : \n" + jsonData);
// ํ์ผ๋ก ์ ์ฅ
File.WriteAllText(path, jsonData);
Debug.Log("Data saved to " + path);
}
}
Path.Combine : ๋ ๊ฐ ์ด์์ ๋ฌธ์์ด์ ๋งค๊ฐ๋ณ์๋ก ๋ฐ๊ณ ์ฌ๋ฐ๋ฅธ ๋๋ ํฐ๋ฆฌ ๊ฒฝ๋ก๋ฅผ ๋ฐํ.JsonUtility.ToJson : ๋งค๊ฐ๋ณ์๋ก ์ง๋ ฌํํ ๊ฐ์ฒด๋ฅผ ๋ฐ๊ณ , ๋ง์ฝ ๋ ๋ฒ์งธ ๋งค๊ฐ๋ณ์์ true ๋ฃ๋๋ค๋ฉด ์ฝ๊ธฐ ์ฝ๊ฒ ๋ณํ.File.WriteAllText : ํด๋น ๊ฒฝ๋ก์ ํ
์คํธ ํ์ผ์ ์ ์ฅ.์ด์ ์๋์ ์์ ๋ฅผ ์คํ์์ผ๋ณด๊ณ ๋ฐฉ๊ธ ์๊ธฐํ ๋๋ ํฐ๋ฆฌ๋ฅผ ์ดํด๋ณด๋ฉด ํ์ผ์ด ์์ฑ๋๊ฑธ ํ์ธํ ์ ์๋ค.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TestJson : MonoBehaviour
{
void Start()
{
PlayerData player = new PlayerData // ๋ฐ์ดํฐ ๊ฐ์ฒด ์์ฑ
{
name = "Player1",
level = 5,
items = new string[] { "sword", "shield" }
};
SaveManager saveManager = new SaveManager(); // SaveManager ๊ฐ์ฒด ์์ฑ
saveManager.SaveData(player); // ์ธ์ด๋ธ ์์
}
}

JSON ํ์ผ๋ก ์ง๋ ฌํ ๋ ๋ชจ์ต

ํ์ผ์ด ์ ์ฅ๋ ์์น


์ ์ฅ๋ ํ์ผ๊ณผ ๋ด์ฉ
์ด๊ฑธ๋ก ์ ์ฅ ๊ธฐ๋ฅ์ ๊ตฌํํ๋ค! ํ์ง๋ง ์ด ์ฝ๋๋ ํ์ผ ์ ์ฅ ๊ณผ์ ์์ ์๊ธธ ์ ์๋ ์ค๋ฅ๋ฅผ ์ฒ๋ฆฌํ์ง ๋ชปํ๋ค. ๋ง์ง๋ง์ผ๋ก ์์ธ ์ฒ๋ฆฌ ๋ก์ง๊น์ง ์ง๋ณด์.
if (!Directory.Exists(Application.persistentDataPath))
{
Directory.CreateDirectory(Application.persistentDataPath);
}
Directory.CreateDirectory : ๋งค๊ฐ๋ณ์๋ก ๋ฃ์ ๊ฒฝ๋ก๋ฅผ ์์ฑtry-catch ๋ฌธ์ผ๋ก ์ ์ฅ ๊ณผ์ ์ค์ ์์์น ๋ชปํ๊ฒ ์๊ธฐ๋ ์ค๋ฅ๋ฅผ ํ์ธํ ์ ์๋ค.try
{
File.WriteAllText(path, jsonData);
Debug.Log("Data saved successfully.");
}
catch (Exception e)
{
Debug.LogError("Failed to save data: " + e.Message);
}
์ด ์์ธ ์ฒ๋ฆฌ๋ฅผ ํฌํจํ ์ ์ฒด์ ์ธ ์ ์ฅ ์ฝ๋๋ ๋ค์๊ณผ ๊ฐ๋ค.
public class SaveManager : MonoBehaviour
{
public void SaveData(PlayerData data)
{
// ์ ์ฅ ๊ฒฝ๋ก ์ค์
string path = Path.Combine(Application.persistentDataPath, "playerData.json");
try
{
// JSON ์ง๋ ฌํ
string jsonData = JsonUtility.ToJson(data, true);
Debug.Log("JSON Data : \n" + jsonData);
// ๊ฒฝ๋ก ํ์ธ ๋ฐ ์์ฑ
if (!Directory.Exists(Application.persistentDataPath))
{
Directory.CreateDirectory(Application.persistentDataPath);
}
// JSON ๋ฐ์ดํฐ ์ ์ฅ
File.WriteAllText(path, jsonData);
Debug.Log("Data saved to " + path);
}
catch (Exception e)
{
Debug.LogError("Failed to save data: " + e.Message);
}
}
}
์ด๋ ๊ฒ ํด์ ์ ์ฅ ๊ธฐ๋ฅ์ ๊ตฌํํด๋ดค๋ค.
๋ค์ ๊ธ์์ ์ด ์ ์ฅํ ํ์ผ์ ์ด๋ป๊ฒ ๋ถ๋ฌ์์ผ ํ๋์ง ์์๋ณด์.
์ ์ฅ์ ๋ํด ์์ธํ๊ฒ ์ค๋ช ํด์ฃผ์ จ๋ค์! ์ข์ ์ ๋ณด ๊ฐ์ฌํฉ๋๋ค!