查看: 3428|回复: 1

[其他] Unity 导出XML配置文件,动态加载场景

[复制链接]

9903

主题

126

听众

7万

积分

首席设计师

Rank: 8Rank: 8

纳金币
53448
精华
316

最佳新人 热心会员 灌水之王 活跃会员 突出贡献 荣誉管理 论坛元老

发表于 2016-2-28 23:16:05 |显示全部楼层

主要功能:
        1.导出场景的配置文件
        2.导出当前场景中资源的AssetBundle
        3.客户端从服务器获取配置文件
        4.解析配置文件,并根据配置文件下载AssetBundle
        5.实例化并还原场景

1.场景设置:将需要导出的场景资源设置为预设


2.将场景配置导出为XML文件
  1. using UnityEngine;
  2. using UnityEditor;
  3. using System.Collections;
  4. using System.Collections.Generic;
  5. using System.Xml;
  6. using System.IO;
  7. using System.Text;

  8. public class ExportSceneToXml : Editor
  9. {
  10.         [MenuItem("Assets/Export Scene To XML From Selection")]
  11.         static void ExportXML()
  12.         {
  13.                 string path = EditorUtility.SaveFilePanel ("Save Resource", "", "New Resource", "xml");
  14.                 if (path.Length != 0)
  15.                 {
  16.                         Object[] selectedAssetList = Selection.GetFiltered (typeof(Object), SelectionMode.DeepAssets);
  17.                        
  18.                         //遍历所有的游戏对象
  19.                         foreach (Object selectObject in selectedAssetList)
  20.                         {
  21.                                 // 场景名称
  22.                                 string sceneName = selectObject.name;
  23.                                 // 场景路径
  24.                                 string scenePath = AssetDatabase.GetAssetPath(selectObject);
  25.                                 // 场景文件
  26.                                 //string xmlPath = path; //Application.dataPath + "/AssetBundles/Prefab/Scenes/" + sceneName + ".xml";
  27.                                 // 如果存在场景文件,删除
  28.                                 if(File.Exists(path)) File.Delete(path);
  29.                                 // 打开这个关卡
  30.                                 EditorApplication.OpenScene(scenePath);

  31.                                 XmlDocument xmlDocument = new XmlDocument();
  32.                                 // 创建XML属性
  33.                                 XmlDeclaration xmlDeclaration = xmlDocument.CreateXmlDeclaration("1.0", "utf-8", null);
  34.                                 xmlDocument.AppendChild(xmlDeclaration);
  35.                                 // 创建XML根标志
  36.                                 XmlElement rootXmlElement = xmlDocument.CreateElement("root");
  37.                                 // 创建场景标志
  38.                                 XmlElement sceneXmlElement = xmlDocument.CreateElement("scene");
  39.                                 sceneXmlElement.SetAttribute("sceneName", sceneName);
  40.                                
  41.                                 foreach (GameObject sceneObject in Object.FindObjectsOfType(typeof(GameObject)))
  42.                                 {
  43.                                         // 如果对象是激活状态
  44.                                         if (sceneObject.transform.parent == null && sceneObject.activeSelf)
  45.                                         {
  46.                                                 // 判断是否是预设
  47.                                                 if(PrefabUtility.GetPrefabType(sceneObject) == PrefabType.PrefabInstance)
  48.                                                 {
  49.                                                         // 获取引用预设对象
  50.                                                         Object prefabObject = EditorUtility.GetPrefabParent(sceneObject);
  51.                                                         if(prefabObject != null)
  52.                                                         {
  53.                                                                 XmlElement gameObjectXmlElement = xmlDocument.CreateElement("gameObject");
  54.                                                                 gameObjectXmlElement.SetAttribute("objectName", sceneObject.name);
  55.                                                                 gameObjectXmlElement.SetAttribute("objectAssetURL",  prefabObject.name);
  56.                                                                
  57.                                                                 XmlElement transformXmlElement = xmlDocument.CreateElement("transform");
  58.                                                                
  59.                                                                 // 位置信息
  60.                                                                 XmlElement positionXmlElement = xmlDocument.CreateElement("position");
  61.                                                                 positionXmlElement.SetAttribute("x", sceneObject.transform.position.x.ToString());
  62.                                                                 positionXmlElement.SetAttribute("y", sceneObject.transform.position.y.ToString());
  63.                                                                 positionXmlElement.SetAttribute("z", sceneObject.transform.position.z.ToString());
  64.                                                                
  65.                                                                 // 旋转信息
  66.                                                                 XmlElement rotationXmlElement = xmlDocument.CreateElement("rotation");
  67.                                                                 rotationXmlElement.SetAttribute("x", sceneObject.transform.rotation.eulerAngles.x.ToString());
  68.                                                                 rotationXmlElement.SetAttribute("y", sceneObject.transform.rotation.eulerAngles.y.ToString());
  69.                                                                 rotationXmlElement.SetAttribute("z", sceneObject.transform.rotation.eulerAngles.z.ToString());
  70.                                                                
  71.                                                                 // 缩放信息
  72.                                                                 XmlElement scaleXmlElement = xmlDocument.CreateElement("scale");
  73.                                                                 scaleXmlElement.SetAttribute("x", sceneObject.transform.localScale.x.ToString());
  74.                                                                 scaleXmlElement.SetAttribute("y", sceneObject.transform.localScale.y.ToString());
  75.                                                                 scaleXmlElement.SetAttribute("z", sceneObject.transform.localScale.z.ToString());
  76.                                                                
  77.                                                                 transformXmlElement.AppendChild(positionXmlElement);
  78.                                                                 transformXmlElement.AppendChild(rotationXmlElement);
  79.                                                                 transformXmlElement.AppendChild(scaleXmlElement);   
  80.                                                                
  81.                                                                 gameObjectXmlElement.AppendChild(transformXmlElement);
  82.                                                                 sceneXmlElement.AppendChild(gameObjectXmlElement);
  83.                                                         }
  84.                                                 }
  85.                                         }
  86.                                 }
  87.                                 rootXmlElement.AppendChild(sceneXmlElement);
  88.                                 xmlDocument.AppendChild(rootXmlElement);
  89.                                 // 保存场景数据
  90.                                 xmlDocument.Save(path);
  91.                                 // 刷新Project视图
  92.                                 AssetDatabase.Refresh();
  93.                         }
  94.                 }
  95.         }
  96. }
复制代码
导出结果参考:
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <root>
  3.   <scene sceneName="DongTaiJiaZaiTest">
  4.     <gameObject objectName="Box" objectAssetURL="Box">
  5.       <transform>
  6.         <position x="-1.293883" y="-0.07" z="1.41" />
  7.         <rotation x="270" y="0" z="0" />
  8.         <scale x="1" y="1" z="1" />
  9.       </transform>
  10.     </gameObject>
  11.     <gameObject objectName="meinv" objectAssetURL="meinv">
  12.       <transform>
  13.         <position x="-1.75" y="1.36" z="11.28" />
  14.         <rotation x="0" y="97.43578" z="0" />
  15.         <scale x="1.09" y="1.09" z="1.09" />
  16.       </transform>
  17.     </gameObject>
  18.     <gameObject objectName="Envirment" objectAssetURL="Envirment">
  19.       <transform>
  20.         <position x="0" y="0" z="0" />
  21.         <rotation x="0" y="0" z="0" />
  22.         <scale x="1" y="1" z="1" />
  23.       </transform>
  24.     </gameObject>
  25.     <gameObject objectName="RigidBodyFpsController" objectAssetURL="RigidBodyFPSController">
  26.       <transform>
  27.         <position x="4.89" y="1.46" z="0.87" />
  28.         <rotation x="0" y="253.2478" z="0" />
  29.         <scale x="1" y="1" z="1" />
  30.       </transform>
  31.     </gameObject>
  32.     <gameObject objectName="Sphere" objectAssetURL="Sphere">
  33.       <transform>
  34.         <position x="-2.63" y="3.28" z="-3.95" />
  35.         <rotation x="270" y="0" z="0" />
  36.         <scale x="1" y="1" z="1" />
  37.       </transform>
  38.     </gameObject>
  39.   </scene>
  40. </root>
复制代码
3.将预设打包为AssetBundle,并上传到服务器
        打包Assetbundle编辑器脚本:
  1. using UnityEngine;
  2. using System.Collections;
  3. using UnityEditor;

  4. public class Test : Editor
  5. {

  6.     [MenuItem("Custom Editor/Create AssetBunldes Main For Android")]
  7.     static void CreateAssetBunldesMainForAndroid()
  8.     {
  9.         //获取在Project视图中选择的所有游戏对象
  10.         Object[] SelectedAsset = Selection.GetFiltered(typeof(Object), SelectionMode.DeepAssets);

  11.         //遍历所有的游戏对象
  12.         foreach (Object obj in SelectedAsset)
  13.         {
  14.             //本地测试:建议最后将Assetbundle放在StreamingAssets文件夹下,如果没有就创建一个,因为移动平台下只能读取这个路径
  15.             //StreamingAssets是只读路径,不能写入
  16.             //服务器下载:就不需要放在这里,服务器上客户端用www类进行下载。
  17.             string targetPath = Application.dataPath + "/StreamingAssets/" + obj.name + "Android" + ".assetbundle";
  18.             if (BuildPipeline.BuildAssetBundle(obj, null, targetPath, BuildAssetBundleOptions.CollectDependencies, BuildTarget.Android))
  19.             {
  20.                 Debug.Log(obj.name + "资源打包成功");
  21.             }
  22.             else
  23.             {
  24.                 Debug.Log(obj.name + "资源打包失败");
  25.             }
  26.         }
  27.         //刷新编辑器
  28.         AssetDatabase.Refresh();

  29.     }
  30.     [MenuItem("Custom Editor/Create AssetBunldes Main For iPhone")]
  31.     static void CreateAssetBunldesMainForiPhone()
  32.     {
  33.         //获取在Project视图中选择的所有游戏对象
  34.         Object[] SelectedAsset = Selection.GetFiltered(typeof(Object), SelectionMode.DeepAssets);
  35.         //遍历所有的游戏对象
  36.         foreach (Object obj in SelectedAsset)
  37.         {
  38.             string targetPath = Application.dataPath + "/StreamingAssets/" + obj.name + "iPhone" + ".assetbundle";
  39.             if (BuildPipeline.BuildAssetBundle(obj, null, targetPath, BuildAssetBundleOptions.CollectDependencies, BuildTarget.iPhone))
  40.             {
  41.                 Debug.Log(obj.name + "资源打包成功");
  42.             }
  43.             else
  44.             {
  45.                 Debug.Log(obj.name + "资源打包失败");
  46.             }
  47.         }
  48.         //刷新编辑器
  49.         AssetDatabase.Refresh();

  50.     }

  51.     [MenuItem("Custom Editor/Create AssetBunldes ALL For Android")]
  52.     static void CreateAssetBunldesALLForAndroid()
  53.     {

  54.         Caching.CleanCache();
  55.         string Path = Application.dataPath + "/StreamingAssets/ALLAndroid.assetbundle";
  56.         Object[] SelectedAsset = Selection.GetFiltered(typeof(Object), SelectionMode.DeepAssets);
  57.         foreach (Object obj in SelectedAsset)
  58.         {
  59.             Debug.Log("Create AssetBunldes name :" + obj);
  60.         }

  61.         //这里注意第二个参数就行
  62.         if (BuildPipeline.BuildAssetBundle(null, SelectedAsset, Path, BuildAssetBundleOptions.CollectDependencies, BuildTarget.Android))
  63.         {
  64.             AssetDatabase.Refresh();
  65.         }
  66.         else
  67.         {

  68.         }
  69.     }
  70.     [MenuItem("Custom Editor/Create AssetBunldes ALL For iPhone")]
  71.     static void CreateAssetBunldesALLForiPhone()
  72.     {

  73.         Caching.CleanCache();


  74.         string Path = Application.dataPath + "/StreamingAssets/ALLiPhone.assetbundle";


  75.         Object[] SelectedAsset = Selection.GetFiltered(typeof(Object), SelectionMode.DeepAssets);

  76.         foreach (Object obj in SelectedAsset)
  77.         {
  78.             Debug.Log("Create AssetBunldes name :" + obj);
  79.         }

  80.         //这里注意第二个参数就行
  81.         if (BuildPipeline.BuildAssetBundle(null, SelectedAsset, Path, BuildAssetBundleOptions.CollectDependencies, BuildTarget.iPhone))
  82.         {
  83.             AssetDatabase.Refresh();
  84.         }
  85.         else
  86.         {

  87.         }
  88.     }
  89.     [MenuItem("Custom Editor/Create Scene For Android")]
  90.     static void CreateSceneALLForAndroid()
  91.     {
  92.         Caching.CleanCache();
  93.         Object[] SelectedAsset = Selection.GetFiltered(typeof(Object), SelectionMode.DeepAssets);
  94.         foreach (Object obj in SelectedAsset)
  95.         {
  96.             string Path = Application.dataPath + "/StreamingAssets/" + obj.name + "Android" + ".unity3d";
  97.             string[] levels = { @"Assets/Scenes/ExportedScene/" + obj.name + ".unity" };
  98.             BuildPipeline.BuildPlayer(levels, Path, BuildTarget.Android, BuildOptions.BuildAdditionalStreamedScenes);
  99.             Debug.Log("Craete Scene" + Path + "Complete!!");
  100.         }
  101.         AssetDatabase.Refresh();
  102.     }

  103.     [MenuItem("Custom Editor/Create Scene For iPhone")]
  104.     static void CreateSceneALLForiPhone()
  105.     {
  106.         Caching.CleanCache();
  107.         Object[] SelectedAsset = Selection.GetFiltered(typeof(Object), SelectionMode.DeepAssets);
  108.         foreach (Object obj in SelectedAsset)
  109.         {
  110.             string Path = Application.dataPath + "/StreamingAssets/" + obj.name + "iPhone" + ".unity3d";
  111.             string[] levels = { @"Assets/Scenes/ExportedScene/" + obj.name + ".unity" };
  112.             BuildPipeline.BuildPlayer(levels, Path, BuildTarget.iPhone, BuildOptions.BuildAdditionalStreamedScenes);
  113.             Debug.Log("Craete Scene" + Path + "Complete!!");
  114.         }
  115.         AssetDatabase.Refresh();
  116.     }

  117. }
复制代码
4.将服务器的路径修改到XML配置文件中,并将XML上传到服务器


5.在Unity客户端下载XML并解析,下载并实例化对应的资源
  1. using UnityEngine;
  2. using System.Collections;
  3. using System.IO;
  4. using System.Collections.Generic;
  5. using System.Xml;

  6. public class GetXMLDoc : MonoBehaviour
  7. {

  8.         string filePath;
  9.         public string XMLDocURL = "http://************.xml";

  10.         void Awake ()
  11.         {
  12.                 filePath = Application.persistentDataPath + "/XMLDoc1028.xml";
  13.                 if (File.Exists (filePath)) {
  14.                         File.Delete (filePath);
  15.                 }
  16.                 WWW www = new WWW (XMLDocURL);
  17.                 StartCoroutine (DownloadXMLDoc (www));

  18.         }

  19.         IEnumerator DownloadXMLDoc (WWW www)
  20.         {
  21.                 yield return www;
  22.                 if (www.isDone) {
  23.                         Debug.Log ("WWW is done");
  24.                         byte[] bts = www.bytes;
  25.                         int length = bts.Length;
  26.                         CreateXMLDoc (filePath, bts, length);
  27.                 }

  28.         }

  29.         void CreateXMLDoc (string path, byte[] info, int lenth)
  30.         {
  31.                 Debug.Log ("Start to create XML");
  32.                 Stream sw;
  33.                 FileInfo t = new FileInfo (path);
  34.                 if (!t.Exists) {
  35.                         sw = t.Create ();

  36.                 } else {
  37.                         return;
  38.                 }
  39.                 sw.Write (info, 0, lenth);
  40.                 sw.Close ();
  41.                 sw.Dispose ();
  42.                 Debug.Log ("XML create sucess");
  43.                 LoadScene ();
  44. //        下载完毕之后可以读取并进行实例化了
  45.         }

  46.         void LoadScene ()
  47.         {
  48.                 Debug.Log ("开始加载");
  49.                 if (File.Exists (filePath)) {
  50.                         XmlDocument xmlDoc = new XmlDocument ();
  51.                         xmlDoc.Load (filePath);
  52.                         XmlNodeList nodeList = xmlDoc.SelectSingleNode ("root").ChildNodes;
  53.                         foreach (XmlElement scene  in nodeList) {
  54.                                 //因为我的XML是把所有游戏对象全部导出, 所以这里判断一下只解析需要的场景中的游戏对象
  55.                                 //JSON和它的原理类似
  56. //                if (!scene.GetAttribute("name").Equals("Assets/StarTrooper.unity"))
  57. //                {
  58. //                    continue;
  59. //                }

  60.                                 foreach (XmlElement gameObjects in scene.ChildNodes) {
  61. //                    取得资源地址
  62.                                         string assetRUL = gameObjects.GetAttribute ("objectAssetURL");
  63.                                         string assetName = gameObjects.GetAttribute ("objectName");
  64.                                         Vector3 pos = Vector3.zero;
  65.                                         Vector3 rot = Vector3.zero;
  66.                                         Vector3 sca = Vector3.zero;
  67.                                         foreach (XmlElement transform in gameObjects.ChildNodes) {
  68.                                                 foreach (XmlElement prs in transform.ChildNodes) {
  69.                                                         if (prs.Name == "position") {

  70.                                                                 pos.x = float.Parse(prs.GetAttribute("x"));
  71.                                                                 pos.y = float.Parse(prs.GetAttribute("y"));
  72.                                                                 pos.z = float.Parse(prs.GetAttribute("z"));

  73. //                                                                foreach (XmlElement position in prs.ChildNodes) {
  74. //                                                                        switch (position.Name) {
  75. //                                                                        case "x":
  76. //                                                                                pos.x = float.Parse (position.InnerText);
  77. //                                                                                break;
  78. //                                                                        case "y":
  79. //                                                                                pos.y = float.Parse (position.InnerText);
  80. //                                                                                break;
  81. //                                                                        case "z":
  82. //                                                                                pos.z = float.Parse (position.InnerText);
  83. //                                                                                break;
  84. //                                                                        }
  85. //                                                                }

  86.                                                         } else if (prs.Name == "rotation") {

  87.                                                                 rot.x = float.Parse (prs.GetAttribute("x"));
  88.                                                                 rot.y = float.Parse(prs.GetAttribute("y"));
  89.                                                                 rot.z = float.Parse(prs.GetAttribute("z"));

  90. //                                                                foreach (XmlElement rotation in prs.ChildNodes) {
  91. //                                                                        switch (rotation.Name) {
  92. //                                                                        case "x":
  93. //                                                                                rot.x = float.Parse (rotation.InnerText);
  94. //                                                                                break;
  95. //                                                                        case "y":
  96. //                                                                                rot.y = float.Parse (rotation.InnerText);
  97. //                                                                                break;
  98. //                                                                        case "z":
  99. //                                                                                rot.z = float.Parse (rotation.InnerText);
  100. //                                                                                break;
  101. //                                                                        }
  102. //                                                                }
  103.                                                         } else if (prs.Name == "scale") {
  104.                                                                 sca.x = float.Parse (prs.GetAttribute("x"));
  105.                                                                 sca.y = float.Parse(prs.GetAttribute("y"));
  106.                                                                 sca.z = float.Parse(prs.GetAttribute("z"));

  107. //                                                                foreach (XmlElement scale in prs.ChildNodes) {
  108. //                                                                        switch (scale.Name) {
  109. //                                                                        case "x":
  110. //                                                                                sca.x = float.Parse (scale.InnerText);
  111. //                                                                                break;
  112. //                                                                        case "y":
  113. //                                                                                sca.y = float.Parse (scale.InnerText);
  114. //                                                                                break;
  115. //                                                                        case "z":
  116. //                                                                                sca.z = float.Parse (scale.InnerText);
  117. //                                                                                break;
  118. //                                                                        }
  119. //                                                                }
  120.                                                         }
  121.                                                 }
  122.                                                 Debug.Log ("准备下载:" + assetRUL);
  123. //                        开始下载并实例化对象
  124.                                                 Debug.Log (assetName + ":pos=" + pos);
  125.                                                 Debug.Log (assetName + ":rot=" + pos);
  126.                                                 Debug.Log (assetName + ":sca=" + pos);
  127.                                                 StartCoroutine (DownloadAsset (new WWW (assetRUL), pos, rot, sca));



  128.                                                 //拿到 旋转 缩放 平移 以后克隆新游戏对象
  129. //                        GameObject ob = (GameObject)Instantiate(Resources.Load(asset), pos, Quaternion.Euler(rot));
  130. //                        ob.transform.localScale = sca;

  131.                     
  132.                                         }
  133.                                 }

  134.                         }

  135.                 }

  136.         }



  137.         IEnumerator DownloadAsset (WWW www, Vector3 pos, Vector3 rot, Vector3 sca)
  138.         {

  139.                 yield return www;
  140.                 if (www.isDone) {
  141. //            yield return Instantiate(www.assetBundle.mainAsset,pos,pos,Quaternion.Euler(rot));
  142.                         GameObject ob = (GameObject)Instantiate (www.assetBundle.mainAsset, pos, Quaternion.Euler (rot));
  143.                         ob.transform.localScale = sca;
  144.                         www.assetBundle.Unload (false);
  145.                 }
  146.         }

  147. }
复制代码
回复

使用道具 举报

7

主题

9

听众

5217

积分

高级设计师

Rank: 6Rank: 6

纳金币
883
精华
3

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

发表于 2016-2-29 09:38:13 |显示全部楼层
感谢分享,值得借鉴
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

关闭

站长推荐上一条 /1 下一条

手机版|纳金网 ( 闽ICP备08008928号

GMT+8, 2024-3-29 13:59 , Processed in 0.117650 second(s), 29 queries .

Powered by Discuz!-创意设计 X2.5

© 2008-2019 Narkii Inc.

回顶部