데이터 저장은 여러가지 방법이 있는데
PlayerPrefs, CSV, XML, JSON, SO 등 의 방법이 있다.
우선 CSV의 경우 엑셀에서 보기 쉽게 정리 할 수 있는 장점이 있지만
생성된 파일을 직접 보고 한 눈에 알아보기에는 큰 어려움이 있다.
대충 이런 엑셀파일을 작성 한 후
CSV파일로 다운로드 받자.
그리고 메모장으로 열어보면
진짜 복잡하게도 나오는데
하여튼 이것을 잘 잘라서 불러와보자.
우선 한 열은 \n으로 구분되며
각 행은 ,로 구분된다.
public class Dialogue : MonoBehaviour
{
Dictionary<int, Item> ItemData = new Dictionary<int, Item>();
string[] rowData;
string[,] columnData;
private void Start()
{
TextAsset csvData = Resources.Load<TextAsset>("./Data/CSV/CSVData");
var data = csvData.text.TrimEnd();
Deserialization(data);
}
public void Deserialization(string originData)
{
rowData = originData.Split('\n');
for (int i = 1; i < rowData.Length; i++)
{
var data = rowData[i].Split(',');
ItemData[int.Parse(data[0])] = new Item()
{
Name = data[1],
Description = data[2],
Price = data[3],
ItemType = data[4],
...
}
}
}
}
역 직렬화 코드를 짜주고
TextAsset 형식으로 불러온 후 TrimEnd()메서드를 이용해 맨 마지막 줄의 모든 여백을 제거한다.
다음은 XML 이다.
XML은 루트 노드, 자식 노드, 데이터 노드 순으로 나눠져 있는데
파일을 열어보면
<?xml version="1.0" encoding="UTF-8"?>
<GameData> //루트 노드
<PlayerData> //자식 노드
<NickName>aa</NickName>
<lv>10</lv>
<hp>100</hp>
</PlayerData>
</GameData>
대충 이런 식으로 저장이 되어있다.
보기에는 어디에 무슨 값이 있는지 CSV에 비해 상대적으로 읽기 편한 장점과
전혀 편하지 않은 작성 방법이 특징이다.
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(); // 에디터에서만 써야함.
}
단 3개의 값을 저장하기 위해 위와 같은 노력을 곁들여야 한다.
불러올 때도
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);
}
이렇게 작성되는데
한 번 작성하고 나면 데이터를 저장하고 불러오는데 편리하지만
한 번 작성하기가 힘들다.
다음은 Json인데 Json중에서도 유니티에서 지원하는 JsonUtillity를 살펴보자
유니티 내부에서 실행 시 실행속도가 0에 가까운 속도를 지원한다고 한다.
중요한건 일반적인 데이터가 아닌
직렬화가 가능한 상태여야만 지원하고
이외에는 오딘이라는 에셋스토어에서 유료로 구매하는 에셋이 필요하다.
자세한 내용은 아래 링크 참조
https://docs.unity3d.com/kr/2019.4/Manual/JSONSerialization.html
public class Character : MonoBehaviour
{
public UserData userData;
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);
}
}
살펴보면 저장 시에는 UserData형식을 그대로 string으로 변환하여 저장이 가능하고
불러 올때는 FromJson에 제너릭 타입을 입력하는 것으로 간단하게 로드가 가능하다.
대신 데이터는 완전히 직렬화 된 상태여야 하는데
[System.Serializable]
public class UserData
{
public string nickname;
public int lv;
public float hp;
public List<string> friends = new List<string>();
public Inventory inven;
}
위 코드처럼 Inventory형식의 inven이라는 필드를 추가하더라도
[System.Serializable]
public class Inventory
{
public int size;
}
해당 형식이 직렬화 되어있다면 문제 없이 저장 가능하다.
TTE