Unity游戏存档之Xml存档
发表于2018-04-09
很多公司的游戏都用的这个XML存档,对于XML的优势这里就和大家介绍了,本篇文章就通过一个Demo讲解如何使用以下脚本对游戏进行存档。
一个管理类 用来管理 存档 读档
#region 快门:存取总控制 public void SaveSnap(string filename) { var xmlDoc = new XmlDocument(); try { var xmlRoot = xmlDoc.CreateElement("Snaps"); xmlDoc.AppendChild(xmlRoot); var xmlModel = xmlDoc.CreateElement("Models"); xmlRoot.AppendChild(xmlModel); ModelManager.Instance.SaveSnap(xmlDoc, xmlModel); var xmlRole = xmlDoc.CreateElement("Roles"); xmlRoot.AppendChild(xmlRole); RoleManager.Instance.SaveSnap(xmlDoc, xmlRole); var xmlTool = xmlDoc.CreateElement("Tools"); xmlRoot.AppendChild(xmlTool); ToolManager.Instance.SaveSnap(xmlDoc, xmlTool); xmlDoc.Save(filename); Debug.Log("XML 存档成功~!!!!!"); } catch { throw new ArgumentOutOfRangeException(); Debug.Log("Save Error"); } xmlDoc = null; } public void LoadSnap(string filename) { if (File.Exists(filename)) { var xmlDoc = new XmlDocument(); try { xmlDoc.Load(filename); var xmlRoot = xmlDoc.DocumentElement; var xmlModel = xmlRoot.SelectSingleNode("Models") as XmlElement; if (xmlModel != null) ModelManager.Instance.LoadSnap(xmlModel); var xmlRole = xmlRoot.SelectSingleNode("Roles") as XmlElement; if (xmlRole != null) RoleManager.Instance.LoadSnap(xmlRole); Debug.Log("222"); var xmlTool = xmlRoot.SelectSingleNode("Tools") as XmlElement; if (xmlTool != null) ToolManager.Instance.LoadSnap(xmlTool); if (Warmtips.Instance.OnHideMessage != null) { Warmtips.Instance.OnHideMessage(); } OperationMessage.Instance.AddTipMessage("读档成功"); Debug.Log("XML 读档~!!!!!"); } catch { throw new ArgumentOutOfRangeException(); Debug.LogError("读档有问题!!!!"); } xmlDoc = null; } }
RoleManager
#region 快门:使用xmlNode存取数据 public void SaveSnap(XmlDocument xmlDoc, XmlElement xmlNode) { foreach (var role in Roles) { var xmlRoleInfo = xmlDoc.CreateElement("RoleInfo"); xmlRoleInfo.SetAttribute("ID", role.OwnId.ToString()); xmlRoleInfo.SetAttribute("HP", role.HP.ToString()); xmlRoleInfo.SetAttribute("Active", role.gameObject.activeSelf.ToString()); xmlRoleInfo.SetAttribute("IsHurt", role.IsHurt.ToString()); xmlRoleInfo.SetAttribute("Position", TxtUtility.Vtr3ToStr(role.gameObject.transform.position)); xmlRoleInfo.SetAttribute("Rotation", TxtUtility.Vtr3ToStr(role.gameObject.transform.eulerAngles)); xmlRoleInfo.SetAttribute("RoleHXJ", role.transform.Find(AppDefine.AirResName).gameObject.activeSelf.ToString()); if (role.ToolList.Count != 0) { string toolName = null; for (int j = 0; j < role.ToolList.Count; j++) { toolName += "," + role.ToolList[j].MainObject.name; } xmlRoleInfo.SetAttribute("ToolList", toolName.TrimStart(',')); } else { xmlRoleInfo.SetAttribute("ToolList", ""); } xmlNode.AppendChild(xmlRoleInfo); } } public void LoadSnap(XmlElement xmlNode) { XmlNodeList nodeList = xmlNode.ChildNodes; foreach (XmlElement itemElement in nodeList) { var role = GetRoleById(itemElement.GetAttribute("ID").ToInt()); Debug.Log(role.OwnId); if (role != null) { role.gameObject.SetActive(Convert.ToBoolean(itemElement.GetAttribute("Active"))); role.HP = itemElement.GetAttribute("HP").ToFloat(); switch (AppSetting.Platform) { case EPlatform.PC: role.gameObject.transform.position = TxtUtility.StrToVtr3(itemElement.GetAttribute("Position")); role.gameObject.transform.eulerAngles = TxtUtility.StrToVtr3(itemElement.GetAttribute("Rotation")); break; case EPlatform.HTC: if (RoleManager.instance.CurrentRoleData.OwnId == role.OwnId) { //Player.instance.gameObject.transform.position = TxtUtility.StrToVtr3(itemElement.GetAttribute("Position")); TelePortManager.Instance.SampleTeleport( TxtUtility.StrToVtr3(itemElement.GetAttribute("Position")), true); } else { role.gameObject.transform.position = TxtUtility.StrToVtr3(itemElement.GetAttribute("Position")); role.gameObject.transform.eulerAngles = TxtUtility.StrToVtr3(itemElement.GetAttribute("Rotation")); } break; case EPlatform.OCULUS: //Debug.LogError(RoleManager.instance.CurrentRoleData.OwnId + "CurrentRole"); //Debug.LogError(role.OwnId + "role"); if (RoleManager.instance.CurrentRoleData.OwnId == role.OwnId) { Debug.LogError(TxtUtility.StrToVtr3(itemElement.GetAttribute("Position"))); RayManager.Get().SetPos(TxtUtility.StrToVtr3(itemElement.GetAttribute("Position"))); } else { role.gameObject.transform.position = TxtUtility.StrToVtr3(itemElement.GetAttribute("Position")); role.gameObject.transform.eulerAngles = TxtUtility.StrToVtr3(itemElement.GetAttribute("Rotation")); } break; } role.transform.Find(AppDefine.AirResName).gameObject.SetActive(Convert.ToBoolean(itemElement.GetAttribute("RoleHXJ"))); if (Convert.ToBoolean(itemElement.GetAttribute("IsHurt"))) { role.Animator.SetBool("hurt", true); } else { role.ClearSitDown(); role.Animator.SetBool("hurt", false); //role.animator.Play("Idle", -1, 0); } //如果不等于"" 说明人物有拿起东西 if (itemElement.GetAttribute("ToolList") != "") { role.ToolList.Clear(); ToolBase tool = null; string[] toolName = itemElement.GetAttribute("ToolList").Split(','); for (int j = 0; j < toolName.Length; j++) { tool = ToolManager.Instance.GetToolBase(toolName[j]); role.ToolList.Add(tool); } } else { //如果没有东西则清空 role.ToolList.Clear(); } } } }
ModelManager
#region 快门:使用xmlNode存取数据 public void SaveSnap(XmlDocument xmlDoc, XmlElement xmlNode) { //消防车 for (int i = 0; i < AccidentPosList.Count; i++) { for (int j = 0; j < AccidentPosList[i].XFCList.Count; j++) { if (AccidentPosList[i].XFCList[j].activeSelf) { var _xmlModelFire = xmlDoc.CreateElement("ModelFire"); _xmlModelFire.SetAttribute("Name", AccidentPosList[i].XFCList[j].name); _xmlModelFire.SetAttribute("Active", AccidentPosList[i].XFCList[j].activeSelf.ToString()); //是否有人引导 _xmlModelFire.SetAttribute("IsCall", AccidentPosList[i].XFCList[j].GetComponent<Fireengine>().Called.ToString()); xmlNode.AppendChild(_xmlModelFire); } } } var ambulance = Ambulance.GetComponent<Ambulance>(); var _xmlModelInfoAmb = xmlDoc.CreateElement("ModelAmbulance"); //救护车 如果打电话应该出现 有人引导开始移动 if (Ambulance.gameObject.activeSelf) { _xmlModelInfoAmb.SetAttribute("Rotation", TxtUtility.Vtr3ToStr(Ambulance.transform.eulerAngles)); _xmlModelInfoAmb.SetAttribute("IsCall", ambulance.Called.ToString()); _xmlModelInfoAmb.SetAttribute("Guided", ambulance.Guided.ToString()); _xmlModelInfoAmb.SetAttribute("Active", Ambulance.gameObject.activeSelf.ToString()); xmlNode.AppendChild(_xmlModelInfoAmb); } else { _xmlModelInfoAmb.SetAttribute("Active", Ambulance.gameObject.activeSelf.ToString()); xmlNode.AppendChild(_xmlModelInfoAmb); } Transform fireCGroup; if (MainEnv.transform.Find("FireControllerGroup")) fireCGroup = MainEnv.transform.Find("FireControllerGroup"); else fireCGroup = MainEnv.transform.Find("FireControlGP"); //消防炮 isActive 消防炮喷水 if (fireCGroup != null && fireCGroup.childCount != 0) { for (int i = 0; i < fireCGroup.childCount; i++) { var _xmlModelFireControl = xmlDoc.CreateElement("xmlModelFireControl"); _xmlModelFireControl.SetAttribute("Name", fireCGroup.GetChild(i).gameObject.name); _xmlModelFireControl.SetAttribute("Rotation", TxtUtility.Vtr3ToStr(fireCGroup.GetChild(i).GetChild(2).eulerAngles)); if (fireCGroup.GetChild(i).GetComponent<Firemonitor>().particleWater == null) _xmlModelFireControl.SetAttribute("IsActive", false.ToString()); else _xmlModelFireControl.SetAttribute("IsActive", fireCGroup.GetChild(i).GetComponent<Firemonitor>().particleWater.activeSelf.ToString()); xmlNode.AppendChild(_xmlModelFireControl); } } } public void LoadSnap(XmlElement xmlNode) { XmlNodeList nodeList = xmlNode.ChildNodes; foreach (XmlElement itemElement in nodeList) { switch (itemElement.Name) { case "ModelFire": for (int i = 0; i < AccidentPosList.Count; i++) { for (int j = 0; j < AccidentPosList[i].XFCList.Count; j++) { if (itemElement.GetAttribute("Name").Equals(AccidentPosList[i].XFCList[j].name)) { var fireengine = AccidentPosList[i].XFCList[j].GetComponent<Fireengine>(); //AccidentPosList[i].XFCList[j].GetComponent<Fireengine>().FireengineWater.SetActive(false); //如果消防车激活 并且引导 就到指定位置喷水 如果没有 则在原地 如果没有显示 则隐藏 if (Convert.ToBoolean(itemElement.GetAttribute("Active"))) { if (Convert.ToBoolean(itemElement.GetAttribute("IsCall"))) { AccidentPosList[i].XFCList[j].transform.position = fireengine.EndPosition + new Vector3(0f, -1.3f, 0f); AccidentPosList[i].XFCList[j].transform.rotation = Quaternion.LookRotation(fireengine.EndDirection, Vector3.up); fireengine.OpenFireengineWater(true); } else { AccidentPosList[i].XFCList[j].transform.rotation = Quaternion.LookRotation(Vector3.Normalize(NodePathList[3].point.transform.position - NodePathList[2].point.transform.position), Vector3.up); AccidentPosList[i].XFCList[j].transform.position = NodePathList[3].point.transform.position; fireengine.OpenFireengineWater(false); fireengine.Called = false; fireengine.IsRealy = false; AccidentPosList[i].XFCList[j].SetActive(true); } } else { if (AccidentPosList[i].XFCList[j].activeSelf) { AccidentPosList[i].XFCList[j].transform.rotation = Quaternion.LookRotation(Vector3.Normalize(NodePathList[3].point.transform.position - NodePathList[2].point.transform.position), Vector3.up); AccidentPosList[i].XFCList[j].transform.position = NodePathList[3].point.transform.position; fireengine.OpenFireengineWater(false); fireengine.Called = false; fireengine.IsRealy = false; AccidentPosList[i].XFCList[j].SetActive(false); } } } } } break; case "ModelAmbulance": var ambulance = Ambulance.GetComponent<Ambulance>(); if (Convert.ToBoolean(itemElement.GetAttribute("Active"))) { if (Convert.ToBoolean(itemElement.GetAttribute("IsCall"))) { if (Convert.ToBoolean(itemElement.GetAttribute("Guided"))) { ambulance._initNavPathed = false; ambulance._isGotoGoal = false; Ambulance.transform.position = ambulance.StartPosition; Ambulance.transform.rotation = Quaternion.identity; ambulance.GoToGoal(new ParamMessage()); } else { Ambulance.gameObject.SetActive(true); Ambulance.transform.position = ambulance.StartPosition; Ambulance.transform.rotation = Quaternion.identity; ambulance.Guided = false; ambulance._initNavPathed = false; ambulance._isGotoGoal = false; } } } else { if (Ambulance.gameObject.activeSelf) { Ambulance.transform.position = ambulance.StartPosition; Ambulance.transform.rotation = Quaternion.identity; ambulance.Called = false; ambulance.Guided = false; ambulance._initNavPathed = false; ambulance._isGotoGoal = false; Ambulance.gameObject.SetActive(false); } } break; case "xmlModelFireControl": Transform fireCGroup; if (MainEnv.transform.Find("FireControllerGroup")) fireCGroup = MainEnv.transform.Find("FireControllerGroup"); else fireCGroup = MainEnv.transform.Find("FireControlGP"); for (int i = 0; i < fireCGroup.childCount; i++) { if (itemElement.GetAttribute("Name").Equals(fireCGroup.GetChild(i).name)) { if (Convert.ToBoolean(itemElement.GetAttribute("IsActive"))) { fireCGroup.GetChild(i).GetChild(2).eulerAngles = TxtUtility.StrToVtr3(itemElement.GetAttribute("Rotation")); fireCGroup.GetChild(i).GetComponent<Firemonitor>().particleWater.SetActive(true); } else { fireCGroup.GetChild(i).GetChild(2).eulerAngles = TxtUtility.StrToVtr3(FireControllerDict[fireCGroup.GetChild(i).name]); if (fireCGroup.GetChild(i).GetComponent<Firemonitor>().particleWater != null) fireCGroup.GetChild(i).GetComponent<Firemonitor>().particleWater.SetActive(false); } } } break; } } }
ToolManager
#region 快门:使用xmlNode存取数据 public void SaveSnap(XmlDocument xmlDoc, XmlElement xmlNode) { //一种未点击警戒绳 一种是点击警戒绳 if (ModelManager.Instance.jjsRoot.transform.childCount != 0) { //如果有警戒绳 for (int i = 0; i < ModelManager.Instance.jjsRoot.transform.childCount; i++) { jjrParent.Add(ModelManager.Instance.jjsRoot.transform.GetChild(i).gameObject); for (int j = 0; j < ModelManager.Instance.jjsRoot.transform.GetChild(i).childCount; j++) { var _xmlToolJJS = xmlDoc.CreateElement("ToolsJJS"); _xmlToolJJS.SetAttribute("ID", i + "." + j); _xmlToolJJS.SetAttribute("Position", TxtUtility.Vtr3ToStr(ModelManager.Instance.jjsRoot.transform.GetChild(i).GetChild(j).position)); _xmlToolJJS.SetAttribute("Rotation", TxtUtility.Vtr3ToStr(ModelManager.Instance.jjsRoot.transform.GetChild(i).GetChild(j).eulerAngles)); _xmlToolJJS.SetAttribute("Scale", TxtUtility.Vtr3ToStr(ModelManager.Instance.jjsRoot.transform.GetChild(i).GetChild(j).localScale)); _xmlToolJJS.SetAttribute("Count", i.ToString() + "." + ModelManager.Instance.jjsRoot.transform.GetChild(i).childCount.ToString()); xmlNode.AppendChild(_xmlToolJJS); } } } else { var _xmlToolJJS = xmlDoc.CreateElement("ToolsJJS"); _xmlToolJJS.SetAttribute("Count", 0.ToString()); xmlNode.AppendChild(_xmlToolJJS); } for (int i = 0; i < toolAllList.Count; i++) { var _xmlToolInfo = xmlDoc.CreateElement("ToolsInfo"); //当前人物ID _xmlToolInfo.SetAttribute("RoleID", RoleManager.Instance.CurrentRoleData.OwnId.ToString()); //_xmlToolInfo.SetAttribute("RoleHXJ", RoleManager.Instance.CurrentRoleData.transform.Find(AppDefine.AirResName).gameObject.activeSelf.ToString()); _xmlToolInfo.SetAttribute("Active", toolAllList[i].activeSelf.ToString()); _xmlToolInfo.SetAttribute("Name", toolAllList[i].name); _xmlToolInfo.SetAttribute("Position", TxtUtility.Vtr3ToStr(toolAllList[i].transform.position)); _xmlToolInfo.SetAttribute("Rotation", TxtUtility.Vtr3ToStr(toolAllList[i].transform.eulerAngles)); if (toolAllList[i].gameObject.tag.CompareTo(GlobalTags.Extinguisher.ToString()) == 0) { _xmlToolInfo.SetAttribute("State", RoleManager.Instance.CurrentRoleData.nWithExtinguisherState.ToString()); } //如果没有父物体 则回到toolRoot if (toolAllList[i].transform.parent == null) { _xmlToolInfo.SetAttribute("Parent", ""); } else { _xmlToolInfo.SetAttribute("Parent", toolAllList[i].transform.parent.name.ToString()); } xmlNode.AppendChild(_xmlToolInfo); } //ToolList 状态 } public void LoadSnap(XmlElement xmlNode) { XmlNodeList nodeList = xmlNode.ChildNodes; foreach (XmlElement itemElement in nodeList) { if (itemElement.Name == "ToolsInfo") { for (int i = 0; i < toolAllList.Count; i++) { if (itemElement.GetAttribute("Name").Equals(toolAllList[i].gameObject.name)) { //RoleManager.Instance.RoleDicts[Convert.ToInt32(itemElement.GetAttribute("RoleID"))].transform.Find(AppDefine.AirResName).gameObject.SetActive(Convert.ToBoolean(itemElement.GetAttribute("RoleHXJ"))); toolAllList[i].gameObject.SetActive(Convert.ToBoolean(itemElement.GetAttribute("Active"))); var role = RoleManager.Instance.GetRoleById(itemElement.GetAttribute("RoleID").ToInt()); if (itemElement.GetAttribute("Parent") == "Bip01 R Hand") { toolAllList[i].gameObject.transform.SetParent(role.RightHand.transform); } else { toolAllList[i].gameObject.transform.SetParent(ToolRoot.transform); } toolAllList[i].gameObject.transform.position = TxtUtility.StrToVtr3(itemElement.GetAttribute("Position")); toolAllList[i].gameObject.transform.eulerAngles = TxtUtility.StrToVtr3(itemElement.GetAttribute("Rotation")); //如果是灭火器 if (toolAllList[i].gameObject.tag.CompareTo(GlobalTags.Extinguisher.ToString()) == 0) { //拿着灭火器的状态,0为没拿,1为拿着,2为喷着 switch (Convert.ToInt32(itemElement.GetAttribute("State"))) { case 0: PutDownExtinguisherState(); break; case 1: PutDownExtinguisherState(); role.GetExtinguisher(toolAllList[i]); break; case 2: role.GetExtinguisher(toolAllList[i]); role.RpcUseExtinguisher(Vector3.zero); break; } } } } } if (itemElement.Name == "ToolsJJS") { //如果有警戒绳 如果没有则删除多余的警戒绳 if (ModelManager.Instance.jjsRoot.transform.childCount != 0) { for (int i = 0; i < ModelManager.Instance.jjsRoot.transform.childCount; i++) { //如果存档没有JJS 则清空JJS if (Convert.ToInt32(itemElement.GetAttribute("Count")) == 0) { RoleManager.Instance.CurrentRoleData.DestoryTools(ModelManager.Instance.jjsRoot.transform.GetChild(i).gameObject); } else { string[] strJJSCount = itemElement.GetAttribute("Count").Split('.'); if (!strJJSCount[1].Equals(ModelManager.Instance.jjsRoot.transform.GetChild(i).childCount)) { //删除多余的JJS for (int j = Convert.ToInt32(strJJSCount[1]); j < ModelManager.Instance.jjsRoot.transform.GetChild(i).childCount; j++) { RoleManager.Instance.CurrentRoleData.DestoryTools(ModelManager.Instance.jjsRoot.transform.GetChild(i).GetChild(j).gameObject); } } } } } } } }
以上就是xml存档的全部内容了,如果大家有更好的方案和代码也可以分享出来。