1. 程式人生 > 其它 >XML設定寫入和讀取地圖

XML設定寫入和讀取地圖

using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Xml;
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;

public class Menu : MonoBehaviour
{
    private static int j = 1;
    private static int k = 1;

    /// <summary> 新增選單欄(寫入、儲存) </summary>
    [MenuItem("GetTransform/獲得所有角色的位置設定XML &8")]
    public static void SetSelectedObjPos()
    {
        //獲得選中的Transfrom元件
        Transform[] objs = Selection.transforms;
        SaveName save = new SaveName();
        for (int i = 0; i < objs.Length; i++)
        {
            SaveByXml(objs[i]);
            //RecursiveSave(objs[i], save);
            Debug.Log("儲存完成");
        }
    }

    /// <summary> 新增選單欄(讀取) </summary>
    [MenuItem("GetTransform/從XML取得角色位置 &9")]
    public static void GetSelectedObjPos()
    {
        //獲得選中的Transfrom元件
        Transform[] objs = Selection.transforms;
        //地址
        string filePath = Application.dataPath + "/byXML.txt";
        //檢視是否有檔案
        //TODO:還需檢查是否名字和層級相同
        //TODO:還需要檢查檢視是否一樣
        if (File.Exists(filePath))
        {
            //載入 XML 文件
            XmlDocument xmlDoc = new XmlDocument();
            //指定URL載入文件
            xmlDoc.Load(filePath);
            //選擇XmlNode匹配(獲得第一個節點)
            XmlNode root = xmlDoc.SelectSingleNode("saveTransform ");
            //獲得root節點的所有子節點(所有第一層GameObject)
            XmlNodeList nodeList = root.ChildNodes;
            for (int i = 0; i < objs.Length; i++)
            {
                for (int j = 0; j < nodeList.Count; j++)
                {
                    //將第一層的資料帶入
                    //LoadByXml(nodeList[j], objs[i].GetChild(j));
                    LoadByXml(nodeList[j], objs[i]);
                }
                Debug.Log("載入遊戲");
            }
        }
    }

    /// <summary> 建立Xml </summary>
    public static void SaveByXml(Transform parent)
    {
        //建立 XML 檔案的儲存路徑
        string filePath = Application.dataPath + "/byXML.txt";
        //如果XML檔案已經存在,就刪除
        if (File.Exists(filePath))
        {
            File.Delete(filePath);
        }
        //建立 XML 文件
        XmlDocument xmlDoc = new XmlDocument();
        //建立跟節點,即最上層的節點
        XmlElement root = xmlDoc.CreateElement("saveTransform");
        //設定該節點的一個屬性
        root.SetAttribute("場景名稱", EditorSceneManager.GetActiveScene().name);
        XmlElement parentObject = xmlDoc.CreateElement("GameObject層級0");
        XmlElement transformXml = xmlDoc.CreateElement("Transform");
        //將Xml加入
        TransformXml(parent, transformXml, xmlDoc);
        parentObject.AppendChild(transformXml);
        RecursiveAllObjs(parent, parentObject, xmlDoc);
        root.AppendChild(parentObject);
        xmlDoc.AppendChild(root);
        xmlDoc.Save(filePath);
    }

    /// <summary> 獲得節點 </summary>
    private static void RecursiveAllObjs(Transform parent, XmlElement parentObject, XmlDocument xmlDoc)
    {
        for (int i = 0; i < parent.childCount; i++) //childCount的數量包括不顯示的物體
        {
            //獲得子物體的 Transform 位置
            var temp = parent.GetChild(i);
            //建立節點遊戲物體
            XmlElement gameObjectXml = xmlDoc.CreateElement("GameObject" + "層級" + j);
            gameObjectXml.SetAttribute("名稱", temp.name);
            XmlElement transformXml = xmlDoc.CreateElement("Transform");
            TransformXml(temp, transformXml, xmlDoc);
            gameObjectXml.AppendChild(transformXml);
            //將transformXml設定父節點為 root
            parentObject.AppendChild(gameObjectXml);
            //再次查詢子類中的Transform。
            if (temp.childCount > 0)
            {
                j++;
                //迭代傳入引數
                RecursiveAllObjs(temp, gameObjectXml, xmlDoc);
                j = 1;
            }
        }
    }

    /// <summary> 將Transform元件內容加入子類XML </summary> 
    private static void TransformXml(Transform parent, XmlElement transformXml, XmlDocument xmlDoc)
    {
        //建立節點position
        XmlElement localPosition = xmlDoc.CreateElement("LocalPosition");
        XmlElement localPositionX = xmlDoc.CreateElement("LocalPositionX");
        XmlElement localPositionY = xmlDoc.CreateElement("LocalPositionY");
        XmlElement localPositionZ = xmlDoc.CreateElement("LocalPositionZ");
        localPositionX.InnerText = parent.localPosition.x.ToString();
        localPositionY.InnerText = parent.localPosition.y.ToString();
        localPositionZ.InnerText = parent.localPosition.z.ToString();
        localPosition.AppendChild(localPositionX);
        localPosition.AppendChild(localPositionY);
        localPosition.AppendChild(localPositionZ);

        //建立節點rotation
        XmlElement localEulerAngles = xmlDoc.CreateElement("LocalEulerAngles");
        XmlElement localEulerAnglesX = xmlDoc.CreateElement("LocalEulerAnglesX");
        XmlElement localEulerAnglesY = xmlDoc.CreateElement("LocalEulerAnglesY");
        XmlElement localEulerAnglesZ = xmlDoc.CreateElement("LocalEulerAnglesZ");
        localEulerAnglesX.InnerText = parent.localEulerAngles.x.ToString();
        localEulerAnglesY.InnerText = parent.localEulerAngles.y.ToString();
        localEulerAnglesZ.InnerText = parent.localEulerAngles.z.ToString();
        localEulerAngles.AppendChild(localEulerAnglesX);
        localEulerAngles.AppendChild(localEulerAnglesY);
        localEulerAngles.AppendChild(localEulerAnglesZ);

        //建立節點scale
        XmlElement localScale = xmlDoc.CreateElement("LocalScale");
        XmlElement localScaleX = xmlDoc.CreateElement("LocalScale");
        XmlElement localScaleY = xmlDoc.CreateElement("LocalScale");
        XmlElement localScaleZ = xmlDoc.CreateElement("LocalScale");
        localScaleX.InnerText = parent.localScale.x.ToString();
        localScaleY.InnerText = parent.localScale.y.ToString();
        localScaleZ.InnerText = parent.localScale.z.ToString();
        localScale.AppendChild(localScaleX);
        localScale.AppendChild(localScaleY);
        localScale.AppendChild(localScaleZ);

        //設定父節點transformXml
        transformXml.AppendChild(localPosition);
        transformXml.AppendChild(localEulerAngles);
        transformXml.AppendChild(localScale);
    }

    /// <summary> 載入節點 </summary>
    public static void LoadByXml(XmlNode noteData, Transform parent)
    {
        int j = 1;
        XmlNodeList notes = noteData.ChildNodes;
        //獲得子物體的零號位都是Transform 位置
        XmlNodeList transformData = notes[0].ChildNodes;
        #region 初始化物體的Transfrom
        //獲得Transform的零號位都是Position
        XmlNodeList LocalPositionData = transformData[0].ChildNodes;
        parent.localPosition = new Vector3(float.Parse(LocalPositionData[0].InnerText), float.Parse(LocalPositionData[1].InnerText), float.Parse(LocalPositionData[2].InnerText));
        //獲得Transform的一號位都是Rotation
        XmlNodeList LocalEulerAnglesData = transformData[1].ChildNodes;
        parent.localEulerAngles = new Vector3(float.Parse(LocalEulerAnglesData[0].InnerText), float.Parse(LocalEulerAnglesData[1].InnerText), float.Parse(LocalEulerAnglesData[2].InnerText));
        //獲得Transform的二號位都是Rotation
        XmlNodeList LocalScaleData = transformData[2].ChildNodes;
        parent.localScale = new Vector3(float.Parse(LocalScaleData[0].InnerText), float.Parse(LocalScaleData[1].InnerText), float.Parse(LocalScaleData[2].InnerText));
        #endregion
        //判斷物體是否還有子物體
        if (notes.Count > 1)
        {
            //排除第一個Transform節點後開始迴圈每一個
            for (int i = 1; i < notes.Count; i++) 
            {
                j++;
                var temp = parent.GetChild(i-1);
                //獲得的是GameObject
                LoadByXml(notes[i], temp);
            }
        }
    }
}