- 직렬화란?
오브젝트 데이터를 저장하거나 전송할 수 있도록 데이터를 연속적인 형식으로 변환하는 과정.
PlayerPrefs
예시 코드
- 데이터를 nickname + ',' + lv + ',' + hp 형식으로 문자열로 변환하여 저장하고, 구분자로 콤마(,)를 사용
- PlayerPrefs.SetString("PlayerData", SaveData); -> PlayerData라는 키에 데이터를 저장
- PlayerPrefs.GetString("PlayerData") -> 저장된 데이터 로드
- 데이터를 콤마(,)를 기준으로 분리하여 datas 배열에 저장
- 간단한 게임 데이터를 저장하는 데 자주 사용되는 Unity의 내장 시스템
- 보안에 취약하므로 중요한 데이터는 보관하지 않는 것이 좋다.
public class Player : MonoBehaviour { public string nickname; public int lv; public float hp; public void Save() { string SaveData = nickname + ',' + lv + ',' + hp; PlayerPrefs.SetString("PlayerData", SaveData); Debug.Log("저장완료"); } public void Load() { string loadData = PlayerPrefs.GetString("PlayerData"); string[] datas = loadData.Split(','); this.nickname = datas[0]; this.lv = int.Parse(datas[1]); this.hp = float.Parse(datas[2]); } }
예시 코드
- Dictionary<string, string> 타입으로, 각 대사의 키를 문자열 형식(예: "3_3")으로 저장하고, 이에 대응하는 값을 저장
- Resources.Load("CSVData")를 통해 Resources 폴더 내의 CSVData라는 파일을 불러온다. 파일의 내용은 TextAsset 객체로 불러와 csvData.text를 통해 문자열로 접근
- Deserialization(data);을 호출하여 CSV 데이터를 파싱하고, 각 대사를 Dictionary에 저장
- rowData 배열에 행별 데이터 저장. 첫 번째 행(0번 인덱스)은 헤더이므로 1부터 시작하여 반복
- 각 행의 데이터를 쉼표(,)를 기준으로 분리하여 data 배열에 저장. 첫 번째 요소는 키, 두 번째 요소는 값
- chatData[data[0]] = data[1];을 통해 각 키와 그에 맞는 값을 Dictionary에 추가
public class Dialogue : MonoBehaviour { private Dictionary<string, string> chatData = new Dictionary<string, string>(); private void Start() { TextAsset csvData = Resources.Load<TextAsset>("CSVData"); var data = csvData.text.TrimEnd(); Deserialization(data); foreach (var item in chatData) { Debug.Log(item); } Debug.Log(Show(3,3)); } public void Deserialization(string originData) { var rowData = originData.Split('\n'); for (int i = 1; i < rowData.Length; i++) { var data = rowData[i].Split(','); chatData[data[0]] = data[1]; } } public string Show(int chapter, int phase) { string t = $"{chapter}_{phase}"; return chatData[t]; } }
예시 코드
- 루트 노드 GameData와 자식 노드 PlayerData를 생성하고, nickname, lv, hp의 값들을 각각 XML 요소로 추가
- AssetDatabase.Refresh();는 Unity 에디터에서 리소스를 갱신할 때 사용되므로 에디터 환경에서만 유효하다.
- Resources.Load("GameDatas") -> Resources 폴더에서 GameDatas.xml 파일을 불러온다.
파일 크기가 큰 데이터를 저장할 때 비효율적
GameDatas.xml <GameData> <PlayerData> <nickname>스파르타</nickname> <lv>10</lv> <hp>100</hp> </PlayerData> </GameData>public class XMLTest : MonoBehaviour
{
public Player player;private void Start() { //CreateXML(player); LoadXML(); }void CreateXML(Player p)
{
XmlDocument xmlDoc = new XmlDocument();//xmlDoc.AppendChild(xmlDoc.CreateXmlDeclaration()); // 루트 노드 XmlNode root = xmlDoc.CreateNode(XmlNodeType.Element, "GameData", string.Empty); xmlDoc.AppendChild(root); // 자식 노드 XmlNode child = xmlDoc.CreateNode(XmlNodeType.Element, "PlayerData", string.Empty); root.AppendChild(child); XmlElement nickname = xmlDoc.CreateElement("nickname"); nickname.InnerText = p.nickname; child.AppendChild(nickname); XmlElement lv = xmlDoc.CreateElement("lv"); lv.InnerText = p.lv.ToString(); child.AppendChild(lv); XmlElement hp = xmlDoc.CreateElement("hp"); hp.InnerText = p.hp.ToString(); child.AppendChild(hp); xmlDoc.Save("./Assets/Resources/GameDatas.xml"); AssetDatabase.Refresh(); // 에디터에서만 써야함. } void LoadXML() { var t = Resources.Load<TextAsset>("GameDatas"); XmlDocument xmlDoc = new XmlDocument(); xmlDoc.LoadXml(t.text); XmlNodeList nodes = xmlDoc.SelectNodes("GameData/PlayerData"); XmlNode playerData = nodes[0]; player.nickname = playerData.SelectSingleNode("nickname").InnerText; player.lv = int.Parse(playerData.SelectSingleNode("lv").InnerText); player.hp = float.Parse(playerData.SelectSingleNode("hp").InnerText); }}
4.JSON
예시 코드
JsonUtility.ToJson(userData)를 사용해 userData 객체를 JSON 형식 문자열로 변환
File.WriteAllText로 쓰기, File.ReadAllText로 읽기
JsonUtility.FromJson(loadData)를 사용해 JSON 문자열을 UserData 객체로 변환
[System.Serializable]를 사용해 JSON으로 직렬화
public class Character : MonoBehaviour { public UserData userData; private void Start() { Load(); } public void Save() { var saveData = JsonUtility.ToJson(userData); Debug.Log(saveData); Debug.Log(Application.persistentDataPath + "/UserData.txt"); File.WriteAllText(Application.persistentDataPath + "/UserData.txt", saveData); } public void Load() { string loadData = File.ReadAllText(Application.persistentDataPath + "/UserData.txt"); userData = JsonUtility.FromJson<UserData>(loadData); } }[System.Serializable]
public class UserData
{
public string nickname;
public int lv;
public float hp;public List<string> friends = new List<string>(); public Inventory inven;}
[System.Serializable]
public class Inventory
{
public int size;
public List items = new List();
}[System.Serializable]
public class Item
{
public int itemId;
}
예시 코드
CreateAssetMenu -> Unity 에디터의 우클릭 메뉴에 ScriptableObject를 생성할 수 있는 옵션을 추가
ScriptableObject를 상속
재사용이 빈번한 데이터 구조에 적합
[CreateAssetMenu(fileName = "SOData", menuName = "SO/Data", order = 1)] public class SOData :ScriptableObject { // Monster public string nickname; public float maxHp; public float maxMoney; public Rigidbody rb; public Collider co; }