最近工作需要用到数据持久化,所以在此分享一下,通过查阅资料,数据持久化大体都是通过xml或者json来进行的。unity为我们自定义了数据持久化方法,但是比较局限,还需要自己来完成数据持久化方法。
(一)unity方法
unity提供了三个方法来实现数据持久化,不过只能对int float string类型进行数据持久化,命令如下
//设定Key=float的值为12f PlayerPrefs.SetFloat("float", 12f); //通过key值“float”获取数值12,如果“float”未设定值,则默认为1f PlayerPrefs.GetFloat("float", 1f); //相关定义与setfloat相同 PlayerPrefs.SetInt("int", 12); PlayerPrefs.GetInt("int", 1); PlayerPrefs.SetString("str", "abc"); PlayerPrefs.GetString("str", "default");
unity提供的方法比较局限,复杂数据还需要自己进行数据可持续化
(二)C#与xml
通过C#编写读取修改xml
1)编写xml
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Xml; using System.IO; namespace MenuData { class Program { static void Main(string[] args) { string filePath = ""; string fileName = "MenuData.xml"; string targetFile = Path.Combine(filePath, fileName); string[] mainMenu = new string[]{ "文件","配置","显示","诊断","投入运行","关机","帮助"}; string[] parentMenu = new string[] { "投入运行助手","测量","调整","软件更新","售后服务","机器人数据","网络配置","辅助软件" }; string[] childMenu = new string[] { "工具","基坐标","固定工具","附加负载数据","外部运动装置","测量点","允差" }; string[] toolMenu = new string[] { "XYZ_4点法","XTZ_参照法","ABC_2点法","ABC_世界坐标系","数字输入","更改名称","工具负荷数据" }; string[] baseMenu = new string[] { "_3点法","间接","数字输入","更改名称" }; XmlDocument xmldoc = new XmlDocument(); //加入XML的声明段落,<?xml version="1.0" encoding="gb2312"?> XmlDeclaration xmldecl; xmldecl = xmldoc.CreateXmlDeclaration("1.0", "gb2312", null); xmldoc.AppendChild(xmldecl); XmlElement menu = xmldoc.CreateElement("", "Menu", ""); xmldoc.AppendChild(menu); //XmlNode root = xmldoc.SelectSingleNode("Menu");//查找<menu> for (int i = 0; i < mainMenu.Length; i++) { XmlElement rootElem = xmldoc.CreateElement(mainMenu[i]);//创建一个<mainMenu[i]>节点 rootElem.SetAttribute("Layer", "1");//设置该节点ID属性 if (i == 4) { for (int j = 0; j < parentMenu.Length; j++) { XmlElement parentElem = xmldoc.CreateElement(parentMenu[j]);//创建一个<parentElem[i]>节点 parentElem.SetAttribute("Layer", "2");//设置该节点ID属性 if (j == 1) { for (int m = 0; m < childMenu.Length; m++) { XmlElement childElem = xmldoc.CreateElement(childMenu[m]);//创建一个<childMenu[i]>节点 childElem.SetAttribute("Layer", "3"); if (m == 0) { for (int ii = 0; ii < toolMenu.Length; ii++) { XmlElement elem = xmldoc.CreateElement(toolMenu[ii]);//创建一个<childMenu[i]>节点 elem.SetAttribute("Layer", "4"); // elem.InnerText = toolMenu[ii]; childElem.AppendChild(elem); } } if (m == 1) { for (int ii = 0; ii < baseMenu.Length; ii++) { XmlElement elem = xmldoc.CreateElement(baseMenu[ii]);//创建一个<childMenu[i]>节点 elem.SetAttribute("Layer", "4"); // elem.SetAttribute("type", "noChild"); //elem.InnerText = baseMenu[ii]; childElem.AppendChild(elem); } } parentElem.AppendChild(childElem); } } rootElem.AppendChild(parentElem); } } menu.AppendChild(rootElem); } xmldoc.Save(targetFile); Console.ReadKey(); } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Xml; namespace XmlRW { class Program { static void Main(string[] args) { XmlDocument xmldoc = new XmlDocument(); //加入XML的声明段落,<?xml version="1.0" encoding="gb2312"?> XmlDeclaration xmldecl; xmldecl = xmldoc.CreateXmlDeclaration("1.0", "gb2312", null); xmldoc.AppendChild(xmldecl); //加入一个根元素 XmlElement xmlelem = xmldoc.CreateElement("", "ToolAndFrame", ""); xmldoc.AppendChild(xmlelem); for (int i = 1; i < 3; i++) { string identifyStr; string id; int count; if(i==1) { identifyStr = "tool"; count = 16; } else { identifyStr = "frame"; count = 32; } //增加次级节点 XmlNode root = xmldoc.SelectSingleNode("ToolAndFrame");//查找<ToolAndFrame> XmlElement elem = xmldoc.CreateElement(identifyStr);//创建一个<identifyStr>节点 elem.SetAttribute("ID", identifyStr);//设置该节点ID属性 //xe1.SetAttribute("ISBN", "2-3631-4");//设置该节点ISBN属性 for(int j=0;j<count;j++) { XmlElement toolElem = xmldoc.CreateElement("elem"+i.ToString()); toolElem.SetAttribute("ID", j.ToString()); toolElem.InnerText = "未知 [?]"; elem.AppendChild(toolElem); } root.AppendChild(elem);//添加到<Employees>节点中 } xmldoc.Save("ToolAndFrame.xml"); } } }
2)读取
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Xml; namespace ReadXml { class Program { static void Main(string[] args) { XmlDocument xmlDoc = new XmlDocument(); xmlDoc.Load("ToolAndFrame.xml"); List<string> strList = new List<string>(); XmlNodeList nodeList = xmlDoc.SelectSingleNode("ToolAndFrame").ChildNodes;//获取Employees节点的所有子节点 foreach (XmlNode temp in nodeList)//遍历所有子节点 { XmlElement elem = (XmlElement)temp;//将子节点类型转换为XmlElement类型 //if (elem.GetAttribute("genre") == "张三")//如果genre属性值为“张三” //{ // elem.SetAttribute("genre", "update张三");//则修改该属性为“update张三” //} XmlNodeList childElem = elem.ChildNodes;//继续获取xe子节点的所有子节点 foreach (XmlNode node in childElem)//遍历 { XmlElement xml = (XmlElement)node;//转换类型 //if (xml.Name == "author")//如果找到 //{ // xml.InnerText = "亚胜";//则修改 //} strList.Add(xml.InnerText); } } foreach(string str in strList) { Console.WriteLine(str); } Console.WriteLine(strList.Count); Console.ReadKey(); } } }
3)查找与更改
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Xml; namespace ChangeText { class Program { static void Main(string[] args) { string id = "tool"; int num = 7; string text = "new Name"; ChangeVal(id, num, text); } public static void ChangeVal(string id,int num,string text) { XmlDocument xmlDoc = new XmlDocument(); xmlDoc.Load("ToolAndFrame.xml"); // List<string> strList = new List<string>(); XmlNodeList nodeList = xmlDoc.SelectSingleNode("ToolAndFrame").ChildNodes;//获取Employees节点的所有子节点 foreach (XmlNode temp in nodeList)//遍历所有子节点 { XmlElement elem = (XmlElement)temp;//将子节点类型转换为XmlElement类型 if (elem.Name == id)//如果elem的名字为“张三” { Console.WriteLine(elem.GetAttribute("ID")); Console.WriteLine(elem.Name); XmlNodeList childElem = elem.ChildNodes;//继续获取xe子节点的所有子节点 foreach (XmlNode node in childElem)//遍历 { XmlElement xml = (XmlElement)node;//转换类型 if (xml.GetAttribute("ID") == num.ToString()) { xml.InnerText = text; break; } } break; } } xmlDoc.Save("ToolAndFrame.xml"); Console.ReadKey(); } } }
本文查找与更改只是更改了属性,如果需要添加节点或者删除节点,只需要查找到相关节点以后,用命令remvoechild即可,最后一定要保存。
(三)json
如果采用json格式实现数据可持续化则可以直接采用unity方法jsonUtility来实现
private string WriteTOJson() { string json = JsonUtility.ToJson(jsonData); return json; } private PersistData ReadFromJson(string json) { PersistData jsonClass = JsonUtility.FromJson<PersistData>(json); return jsonClass; }
class PersistData { public long width; public long top; public long left; public long height; }
对于list格式的参数进行解析时要增加serializable
如下所示:
#region jsonClass [Serializable] public class ListModel { public int ListContentId; public string CName;//新版本 public string EName;//新版本 //public string Name;//旧版本 public string BigResourcePath; public string BigResourceName; public string BigResourceType; public string SmallResourcePath; public string SmallResourceName; public string SmallResourceType; public DateTime UpdateTime; public int Order; public int Level; public int ParentId; //public int ListContentId; //public string Name; //public string BigResourcePath; //public string BigResourceName; //public string BigResourceType; //public string SmallResourcePath; //public string SmallResourceName; //public string SmallResourceType; //public DateTime UpdateTime; //public int Order; //public int Level; //public int ParentID; } [Serializable] public class ListLevelModel { public bool success; public List<ListModel> data; } #endregion
listLevelModel = JsonUtility.FromJson<ListLevelModel>(jsonlist);
(四)LitJson
采用unity自带的解析方法时,在解析list时需要构筑一个带list的类,不能直接解析成list,而litjson可以如:
allComments = JsonMapper.ToObject<List<CommentElem>>(json);
也可以直接解析出所需要的参数,如下所示,可以直接获取到det下add的值
JsonData data = JsonMapper.ToObject(json); string str = data["Det"]["add"]
PS:如果xml需要跳过注释可用
if(temp is XmlComment) { continue; }