XML在开发中使用也很频繁,此时要以标签的形式来组织数据结构。C#提供了创建、解析、修改、查询等方法,可以很方便地操作它
创建XML 需要System.Xml
命名空间
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 using UnityEngine;using System.Xml;using System.IO;public class XMLCreate : MonoBehaviour { void Start () { XmlDocument xmlDoc = new XmlDocument(); XmlDeclaration xmlDeclaration = xmlDoc.CreateXmlDeclaration("1.0" , "UTF-8" , null ); xmlDoc.AppendChild(xmlDeclaration); XmlElement root = xmlDoc.CreateElement("XmlRoot" ); xmlDoc.AppendChild(root); XmlElement group = xmlDoc.CreateElement("Group" ); group .SetAttribute("username" , "ATAO2017" ); group .SetAttribute("password" , "123456" ); root.AppendChild(group ); using (StringWriter stringWriter = new StringWriter()) { using (XmlTextWriter xmlTextWriter = new XmlTextWriter(stringWriter)) { xmlDoc.WriteTo(xmlTextWriter); xmlTextWriter.Flush(); Debug.Log(stringWriter.ToString()); } } } }
XML读取与修改 XML可以作为字符串来传递。我们可以动态读取XML字符串中的内容,并且修改它的内容,以重新生成新的XML字符串。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 using UnityEngine;using System.Xml;using System.IO;public class XMLProcessing : MonoBehaviour { string xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><XmlRoot><Group username=\"ATAO2017\" password=\"123456\" /></XmlRoot>" ; void Start () { XmlDocument xmlDoc = new XmlDocument(); xmlDoc.LoadXml(xml); XmlNode nodes = xmlDoc.SelectSingleNode("XmlRoot" ); foreach (XmlNode node in nodes.ChildNodes) { string username = node.Attributes["username" ].Value; string password = node.Attributes["password" ].Value; Debug.LogFormat($"username={username} password = {password} " ); node.Attributes["password" ].Value = "88888888" ; } using (StringWriter stringWriter = new StringWriter()) { using (XmlTextWriter xmlTextWriter = new XmlTextWriter(stringWriter)) { xmlDoc.WriteTo(xmlTextWriter); xmlTextWriter.Flush(); Debug.Log(stringWriter.ToString()); } } } }
XML本地文件读写 xmlDocument类也提供了从文件中读取XML,或者将XML写入本地路径的方法。
新建XMLIOTest
脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 using UnityEngine;using UnityEditor;using System.Xml;using System.IO;public class XMLIOTest { [MenuItem("XML/WriteXml" ) ] static void XmlWrite () { string xmlPath = Path.Combine(Application.dataPath, "test.xml" ); if (File.Exists(xmlPath)) File.Delete(xmlPath); XmlDocument xmlDoc = new XmlDocument(); XmlDeclaration xmlDeclaration = xmlDoc.CreateXmlDeclaration("1.0" , "UTF-8" , null ); xmlDoc.AppendChild(xmlDeclaration); XmlElement root = xmlDoc.CreateElement("Root" ); xmlDoc.AppendChild(root); for (int i = 0 ; i < 3 ; i++) { XmlElement group = xmlDoc.CreateElement("Group" ); group .SetAttribute("id" , i.ToString()); group .SetAttribute("username" , "ATAO2017" ); group .SetAttribute("password" , "123456" ); root.AppendChild(group ); } xmlDoc.Save(xmlPath); AssetDatabase.Refresh(); } [MenuItem("XML/LoadXml" ) ] static void XMLLoad () { string xmlPath = Path.Combine(Application.dataPath, "test.xml" ); if (File.Exists(xmlPath)) { XmlDocument xmlDoc = new XmlDocument(); xmlDoc.Load(xmlPath); XmlNode root = xmlDoc.SelectSingleNode("Root" ); foreach (XmlNode group in root.ChildNodes) { string id = group .Attributes["id" ].Value; string username = group .Attributes["username" ].Value; string password = group .Attributes["password" ].Value; Debug.Log($"id = {id} ,username = {username} ,password = {password} " ); } } } }
YAML JSON的可读性差,XML的格式要求很严格
Unity采用了YAML格式来描述结构,它的预览性以及编辑性都非常好,数据与变量通过冒号来连接(必须带空格),例如,游戏中一些服务器列表的配置,或者调试性的开关,太不方便配置在表格中的数据,或者修改比较频繁的数据都可以使用YAML来配置,随时用随时改
YAML 入门教程 | 菜鸟教程 (runoob.com)
YamlDotNet 在Asset Store中免费添加YamlDotNet,支持PC和移动端,我们Download后,Import进入工程中
序列化和反序列化 YamlDotNet提供了运行时序列化和反序列化的方法。对于参与序列化的类中的变量,其属性必需设置成get和set ,不然无法序列化
新建YAMLDaTaProcessing
脚本
注意:不能在使用了Assembly Definition的文件夹下存放此脚本,即使在VS内添加了自定义Assembly对YamlDotNet的引用,Unity还是会报错
使用YamlDotNet序列化方法,可以不用把Class添加[System.Serializable]特性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 using System.Collections.Generic;using UnityEngine;using YamlDotNet.Serialization;public class YAMLDaTaProcessing : MonoBehaviour { void Start () { Data data = new Data(); data.name = "ATAO2017" ; data.password = "123456" ; data.list = new List<string >() { "A" , "B" , "C" }; Serializer serializer = new Serializer(); string yaml = serializer.Serialize(data); Debug.LogFormat("serializer : \n{0}" , yaml); Deserializer deserializer = new Deserializer(); Data data1 = deserializer.Deserialize<Data>(yaml); Debug.LogFormat("deserializer : name={0} password={1}" , data1.name, data1.password); } class Data { public string name { get ; set ; } public string password; public List<string > list { get ; set ; } } }
Serializable特性仅仅是一个标签,每一种序列化方式(不管是JSON、Xml还是Yaml)都有自己的一套方法,他们都按照自己的规则事件了ISerializable接口,有的在序列化之前需要确认Serializable特性,否则无法序列化;有的不需要查看Serializable特性,通过反射进行序列化。
读取配置 在游戏中,一些服务器列表或者一些临时调试的配置信息,可能需要频繁地添加、删除和修改。由于这些测试数据都是临时性的,就不太适合配置在Excel表格中。
我们将配置信息储存在yaml中,当包打出来后,直接修改配置文件就可以立即生效到游戏中。
我们在Unity的Assets文件目录下新建StreamingAssets文件夹,并新建yaml.txt,在其中输入
1 2 3 4 5 6 ServerList : 192.168 .1 .1 Port : 8080 Debug : true
在Unity中新建YAMLReadingConfig
脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 using System.Collections;using System.Collections.Generic;using System.IO;using UnityEngine;using YamlDotNet.RepresentationModel;public class YAMLReadingConfig : MonoBehaviour { private IDictionary<YamlNode, YamlNode> m_MappingData; void Start () { string document = File.ReadAllText(Path.Combine(Application.streamingAssetsPath, "yaml.txt" )); var input = new StringReader(document); var yaml = new YamlStream(); yaml.Load(input); var mapping = (YamlMappingNode)yaml.Documents[0 ].RootNode; m_MappingData = mapping.Children; } private void OnGUI () { GUILayout.Label(string .Format("<size=50>服务器列表 :{0}</size>" , m_MappingData["ServerList" ])); GUILayout.Label(string .Format("<size=50>服务器端口 :{0}</size>" , m_MappingData["Port" ])); GUILayout.Label(string .Format("<size=50>是否调试 :{0}</size>" , m_MappingData["Debug" ])); } }
在Unity中运行后