许可优化
产品
解决方案
服务支持
关于
软件库
当前位置:服务支持 >  软件文章 >  Unity3D 将场景导出XML或JSON或二进制并且解析还原场景

Unity3D 将场景导出XML或JSON或二进制并且解析还原场景

阅读数 5
点赞 0
article_banner

导出Unity场景的所有游戏对象信息,一种是XML一种是JSON。本篇文章我们把游戏场景中游戏对象的、旋转、缩放、平移与Prefab的名称导出在XML与JSON中。然后解析刚刚导出的XML或JSON通过脚本把导出的游戏场景还原。在Unity官网上下载随便下载一个demo Project,如下图所示这是我刚刚在官网上下载的一个范例程序。


   接着将层次视图中的所有游戏对象都封装成Prefab保存在资源路径中,这里注意一下如果你的Prefab绑定的脚本中有public Object 的话 ,需要在代码中改一下。。用 Find() FindTag()这类方法在脚本中Awake()方法中来拿,不然Prefab动态加载的时候无法赋值的,如下图所示,我把封装的Prefab对象都放在了Resources/Prefab文件夹下。


OK,现在我们就需要编写我们的导出工具、在Project视图中创建Editor文件夹,接着创建脚本MyEditor 。如下图所示。


因为编辑的游戏场景数量比较多,导出的时候我们需要遍历所有的游戏场景,一个一个的读取场景信息。然后取得游戏场景中所有游戏对象的Prefab的 名称 旋转 缩放 平移。有关XML的使用请大家看我的上一篇文章: Unity3D 使用 C#合成解析XML与JSON 代码中我只注释重点的部分,嘿嘿。

MyEditor.cs

  1. using UnityEngine;
  2. using System.Collections;
  3. using UnityEditor;
  4. using System.Collections.Generic;
  5. using System.Xml;
  6. using System.IO;
  7. using System.Text;
  8. using LitJson;
  9. public class MyEditor : Editor
  10. {
  11. //将所有游戏场景导出为XML格式
  12. [MenuItem ("GameObject/ExportXML")]
  13. static void ExportXML ()
  14. {
  15. string filepath = Application.dataPath + @"/StreamingAssets/my.xml";
  16. if(!File.Exists (filepath))
  17. {
  18. File.Delete(filepath);
  19. }
  20. XmlDocument xmlDoc = new XmlDocument();
  21. XmlElement root = xmlDoc.CreateElement("gameObjects");
  22. //遍历所有的游戏场景
  23. foreach (UnityEditor.EditorBuildSettingsScene S in UnityEditor.EditorBuildSettings.scenes)
  24. {
  25. //当关卡启用
  26. if (S.enabled)
  27. {
  28. //得到关卡的名称
  29. string name = S.path;
  30. //打开这个关卡
  31. EditorApplication.OpenScene(name);
  32. XmlElement scenes = xmlDoc.CreateElement("scenes");
  33. scenes.SetAttribute("name",name);
  34. foreach (GameObject obj in Object.FindObjectsOfType(typeof(GameObject)))
  35. {
  36. if (obj.transform.parent == null)
  37. {
  38. XmlElement gameObject = xmlDoc.CreateElement("gameObjects");
  39. gameObject.SetAttribute("name",obj.name);
  40. gameObject.SetAttribute("asset",obj.name + ".prefab");
  41. XmlElement transform = xmlDoc.CreateElement("transform");
  42. XmlElement position = xmlDoc.CreateElement("position");
  43. XmlElement position_x = xmlDoc.CreateElement("x");
  44. position_x.InnerText = obj.transform.position.x+"";
  45. XmlElement position_y = xmlDoc.CreateElement("y");
  46. position_y.InnerText = obj.transform.position.y+"";
  47. XmlElement position_z = xmlDoc.CreateElement("z");
  48. position_z.InnerText = obj.transform.position.z+"";
  49. position.AppendChild(position_x);
  50. position.AppendChild(position_y);
  51. position.AppendChild(position_z);
  52. XmlElement rotation = xmlDoc.CreateElement("rotation");
  53. XmlElement rotation_x = xmlDoc.CreateElement("x");
  54. rotation_x.InnerText = obj.transform.rotation.eulerAngles.x+"";
  55. XmlElement rotation_y = xmlDoc.CreateElement("y");
  56. rotation_y.InnerText = obj.transform.rotation.eulerAngles.y+"";
  57. XmlElement rotation_z = xmlDoc.CreateElement("z");
  58. rotation_z.InnerText = obj.transform.rotation.eulerAngles.z+"";
  59. rotation.AppendChild(rotation_x);
  60. rotation.AppendChild(rotation_y);
  61. rotation.AppendChild(rotation_z);
  62. XmlElement scale = xmlDoc.CreateElement("scale");
  63. XmlElement scale_x = xmlDoc.CreateElement("x");
  64. scale_x.InnerText = obj.transform.localScale.x+"";
  65. XmlElement scale_y = xmlDoc.CreateElement("y");
  66. scale_y.InnerText = obj.transform.localScale.y+"";
  67. XmlElement scale_z = xmlDoc.CreateElement("z");
  68. scale_z.InnerText = obj.transform.localScale.z+"";
  69. scale.AppendChild(scale_x);
  70. scale.AppendChild(scale_y);
  71. scale.AppendChild(scale_z);
  72. transform.AppendChild(position);
  73. transform.AppendChild(rotation);
  74. transform.AppendChild(scale);
  75. gameObject.AppendChild(transform);
  76. scenes.AppendChild(gameObject);
  77. root.AppendChild(scenes);
  78. xmlDoc.AppendChild(root);
  79. xmlDoc.Save(filepath);
  80. }
  81. }
  82. }
  83. }
  84. //刷新Project视图, 不然需要手动刷新哦
  85. AssetDatabase.Refresh();
  86. }
  87. //将所有游戏场景导出为JSON格式
  88. [MenuItem ("GameObject/ExportJSON")]
  89. static void ExportJSON ()
  90. {
  91. string filepath = Application.dataPath + @"/StreamingAssets/json.txt";
  92. FileInfo t = new FileInfo(filepath);
  93. if(!File.Exists (filepath))
  94. {
  95. File.Delete(filepath);
  96. }
  97. StreamWriter sw = t.CreateText();
  98. StringBuilder sb = new StringBuilder ();
  99. JsonWriter writer = new JsonWriter (sb);
  100. writer.WriteObjectStart ();
  101. writer.WritePropertyName ("GameObjects");
  102. writer.WriteArrayStart ();
  103. foreach (UnityEditor.EditorBuildSettingsScene S in UnityEditor.EditorBuildSettings.scenes)
  104. {
  105. if (S.enabled)
  106. {
  107. string name = S.path;
  108. EditorApplication.OpenScene(name);
  109. writer.WriteObjectStart();
  110. writer.WritePropertyName("scenes");
  111. writer.WriteArrayStart ();
  112. writer.WriteObjectStart();
  113. writer.WritePropertyName("name");
  114. writer.Write(name);
  115. writer.WritePropertyName("gameObject");
  116. writer.WriteArrayStart ();
  117. foreach (GameObject obj in Object.FindObjectsOfType(typeof(GameObject)))
  118. {
  119. if (obj.transform.parent == null)
  120. {
  121. writer.WriteObjectStart();
  122. writer.WritePropertyName("name");
  123. writer.Write(obj.name);
  124. writer.WritePropertyName("position");
  125. writer.WriteArrayStart ();
  126. writer.WriteObjectStart();
  127. writer.WritePropertyName("x");
  128. writer.Write(obj.transform.position.x.ToString("F5"));
  129. writer.WritePropertyName("y");
  130. writer.Write(obj.transform.position.y.ToString("F5"));
  131. writer.WritePropertyName("z");
  132. writer.Write(obj.transform.position.z.ToString("F5"));
  133. writer.WriteObjectEnd();
  134. writer.WriteArrayEnd();
  135. writer.WritePropertyName("rotation");
  136. writer.WriteArrayStart ();
  137. writer.WriteObjectStart();
  138. writer.WritePropertyName("x");
  139. writer.Write(obj.transform.rotation.eulerAngles.x.ToString("F5"));
  140. writer.WritePropertyName("y");
  141. writer.Write(obj.transform.rotation.eulerAngles.y.ToString("F5"));
  142. writer.WritePropertyName("z");
  143. writer.Write(obj.transform.rotation.eulerAngles.z.ToString("F5"));
  144. writer.WriteObjectEnd();
  145. writer.WriteArrayEnd();
  146. writer.WritePropertyName("scale");
  147. writer.WriteArrayStart ();
  148. writer.WriteObjectStart();
  149. writer.WritePropertyName("x");
  150. writer.Write(obj.transform.localScale.x.ToString("F5"));
  151. writer.WritePropertyName("y");
  152. writer.Write(obj.transform.localScale.y.ToString("F5"));
  153. writer.WritePropertyName("z");
  154. writer.Write(obj.transform.localScale.z.ToString("F5"));
  155. writer.WriteObjectEnd();
  156. writer.WriteArrayEnd();
  157. writer.WriteObjectEnd();
  158. }
  159. }
  160. writer.WriteArrayEnd();
  161. writer.WriteObjectEnd();
  162. writer.WriteArrayEnd();
  163. writer.WriteObjectEnd();
  164. }
  165. }
  166. writer.WriteArrayEnd();
  167. writer.WriteObjectEnd ();
  168. sw.WriteLine(sb.ToString());
  169. sw.Close();
  170. sw.Dispose();
  171. AssetDatabase.Refresh();
  172. }
  173. }
csharp
运行
OK。此时我们就可以导出游戏场景的信息拉,注意游戏场景的需要现在Project Setting 中注册。点击 GameObject – > Export    XML 和 GameObject – > ExportJson 菜单项即可开始生成。


如下图所示,场景导出完毕后,会将xml 与Json 文件保存在StreamingAssets路径下,放在这里的原因是方便移动平台移植,因为它们属于二进制文件,移动平台在读取二进制文件的路径是不一样的。一定要放在这里喔。


接着,我继续创建两个游戏场景,一个用来解析XML的场景,一个用来解析JSON的场景。 

XML场景中,创建一个空的游戏对象,把XML.cs挂上去。

  1. using UnityEngine;
  2. using System.Collections;
  3. using System.Xml;
  4. using System.IO;
  5. public class XML : MonoBehaviour {
  6. // Use this for initialization
  7. void Start ()
  8. {
  9. //电脑和iphong上的路径是不一样的,这里用标签判断一下。
  10. #if UNITY_EDITOR
  11. string filepath = Application.dataPath +"/StreamingAssets"+"/my.xml";
  12. #elif UNITY_IPHONE
  13. string filepath = Application.dataPath +"/Raw"+"/my.xml";
  14. #endif
  15. //如果文件存在话开始解析。
  16. if(File.Exists (filepath))
  17. {
  18. XmlDocument xmlDoc = new XmlDocument();
  19. xmlDoc.Load(filepath);
  20. XmlNodeList nodeList=xmlDoc.SelectSingleNode("gameObjects").ChildNodes;
  21. foreach(XmlElement scene in nodeList)
  22. {
  23. //因为我的XML是把所有游戏对象全部导出, 所以这里判断一下只解析需要的场景中的游戏对象
  24. //JSON和它的原理类似
  25. if(!scene.GetAttribute("name").Equals("Assets/StarTrooper.unity"))
  26. {
  27. continue;
  28. }
  29. foreach(XmlElement gameObjects in scene.ChildNodes)
  30. {
  31. string asset = "Prefab/" + gameObjects.GetAttribute("name");
  32. Vector3 pos = Vector3.zero;
  33. Vector3 rot = Vector3.zero;
  34. Vector3 sca = Vector3.zero;
  35. foreach(XmlElement transform in gameObjects.ChildNodes)
  36. {
  37. foreach(XmlElement prs in transform.ChildNodes)
  38. {
  39. if(prs.Name == "position")
  40. {
  41. foreach(XmlElement position in prs.ChildNodes)
  42. {
  43. switch(position.Name)
  44. {
  45. case "x":
  46. pos.x = float.Parse(position.InnerText);
  47. break;
  48. case "y":
  49. pos.y = float.Parse(position.InnerText);
  50. break;
  51. case "z":
  52. pos.z = float.Parse(position.InnerText);
  53. break;
  54. }
  55. }
  56. }else if(prs.Name == "rotation")
  57. {
  58. foreach(XmlElement rotation in prs.ChildNodes)
  59. {
  60. switch(rotation.Name)
  61. {
  62. case "x":
  63. rot.x = float.Parse(rotation.InnerText);
  64. break;
  65. case "y":
  66. rot.y = float.Parse(rotation.InnerText);
  67. break;
  68. case "z":
  69. rot.z = float.Parse(rotation.InnerText);
  70. break;
  71. }
  72. }
  73. }else if(prs.Name == "scale")
  74. {
  75. foreach(XmlElement scale in prs.ChildNodes)
  76. {
  77. switch(scale.Name)
  78. {
  79. case "x":
  80. sca.x = float.Parse(scale.InnerText);
  81. break;
  82. case "y":
  83. sca.y = float.Parse(scale.InnerText);
  84. break;
  85. case "z":
  86. sca.z = float.Parse(scale.InnerText);
  87. break;
  88. }
  89. }
  90. }
  91. }
  92. //拿到 旋转 缩放 平移 以后克隆新游戏对象
  93. GameObject ob = (GameObject)Instantiate(Resources.Load(asset),pos,Quaternion.Euler(rot));
  94. ob.transform.localScale = sca;
  95. }
  96. }
  97. }
  98. }
  99. }
  100. // Update is called once per frame
  101. void Update ()
  102. {
  103. }
  104. void OnGUI()
  105. {
  106. if(GUI.Button(new Rect(0,0,200,200),"XML WORLD"))
  107. {
  108. Application.LoadLevel("JSONScene");
  109. }
  110. }
  111. }
csharp
运行

接着JSON场景中,创建一个空的游戏对象,把JSON.cs挂上去。

  1. using UnityEngine;
  2. using System.Collections;
  3. using System.IO;
  4. using LitJson;
  5. public class JSON : MonoBehaviour {
  6. // Use this for initialization
  7. void Start ()
  8. {
  9. #if UNITY_EDITOR
  10. string filepath = Application.dataPath +"/StreamingAssets"+"/json.txt";
  11. #elif UNITY_IPHONE
  12. string filepath = Application.dataPath +"/Raw"+"/json.txt";
  13. #endif
  14. StreamReader sr = File.OpenText(filepath);
  15. string strLine = sr.ReadToEnd();
  16. JsonData jd = JsonMapper.ToObject(strLine);
  17. JsonData gameObjectArray = jd["GameObjects"];
  18. int i,j,k;
  19. for (i = 0; i < gameObjectArray.Count; i++)
  20. {
  21. JsonData senseArray = gameObjectArray[i]["scenes"];
  22. for (j = 0; j < senseArray.Count; j++)
  23. {
  24. string sceneName = (string)senseArray[j]["name"];
  25. if(!sceneName.Equals("Assets/StarTrooper.unity"))
  26. {
  27. continue;
  28. }
  29. JsonData gameObjects = senseArray[j]["gameObject"];
  30. for (k = 0; k < gameObjects.Count; k++)
  31. {
  32. string objectName = (string)gameObjects[k]["name"];
  33. string asset = "Prefab/" + objectName;
  34. Vector3 pos = Vector3.zero;
  35. Vector3 rot = Vector3.zero;
  36. Vector3 sca = Vector3.zero;
  37. JsonData position = gameObjects[k]["position"];
  38. JsonData rotation = gameObjects[k]["rotation"];
  39. JsonData scale = gameObjects[k]["scale"];
  40. pos.x = float.Parse((string)position[0]["x"]);
  41. pos.y = float.Parse((string)position[0]["y"]);
  42. pos.z = float.Parse((string)position[0]["z"]);
  43. rot.x = float.Parse((string)rotation[0]["x"]);
  44. rot.y = float.Parse((string)rotation[0]["y"]);
  45. rot.z = float.Parse((string)rotation[0]["z"]);
  46. sca.x = float.Parse((string)scale[0]["x"]);
  47. sca.y = float.Parse((string)scale[0]["y"]);
  48. sca.z = float.Parse((string)scale[0]["z"]);
  49. GameObject ob = (GameObject)Instantiate(Resources.Load(asset),pos,Quaternion.Euler(rot));
  50. ob.transform.localScale = sca;
  51. }
  52. }
  53. }
  54. }
  55. // Update is called once per frame
  56. void Update () {
  57. }
  58. void OnGUI()
  59. {
  60. if(GUI.Button(new Rect(0,0,200,200),"JSON WORLD"))
  61. {
  62. Application.LoadLevel("XMLScene");
  63. }
  64. }
  65. }
csharp
运行
本例XML和JSON的解析与还原场景,在IOS真实设备上测试通过。



本例的下载地址:http://download.csdn.net/detail/e295166319/9664828

最近在做客户端与服务器的交互,使用JSON 和XML会感觉数据量太大,影响效率。最后使用二进制的方式来完成。如下图所示,使用二进制可以把空间节省到803K ,是不是很不错呢? 下面我们开始学习如何制作吧。



导出场景时增加导出二进制文件选项,代码如下。

  1. [MenuItem ("GameObject/BINARY")]
  2. static void XMLJSONTOBinary ()
  3. {
  4. string filepath = Application.dataPath + @"/StreamingAssets/binary.txt";
  5. if(File.Exists (filepath))
  6. {
  7. File.Delete(filepath);
  8. }
  9. FileStream fs = new FileStream(filepath, FileMode.Create);
  10. BinaryWriter bw = new BinaryWriter(fs);
  11. foreach (UnityEditor.EditorBuildSettingsScene S in UnityEditor.EditorBuildSettings.scenes)
  12. {
  13. if (S.enabled)
  14. {
  15. string name = S.path;
  16. EditorApplication.OpenScene(name);
  17. foreach (GameObject obj in Object.FindObjectsOfType(typeof(GameObject)))
  18. {
  19. if (obj.transform.parent == null)
  20. {
  21. //注解 直接写入字符串
  22. bw.Write(name);
  23. bw.Write(obj.name);
  24. short posx = (short)(obj.transform.position.x * 100);
  25. bw.Write(posx);
  26. bw.Write((short)(obj.transform.position.y * 100.0f));
  27. bw.Write((short)(obj.transform.position.z * 100.0f));
  28. bw.Write((short)(obj.transform.rotation.eulerAngles.x * 100.0f));
  29. bw.Write((short)(obj.transform.rotation.eulerAngles.y * 100.0f));
  30. bw.Write((short)(obj.transform.rotation.eulerAngles.z * 100.0f));
  31. bw.Write((short)(obj.transform.localScale.x * 100.0f));
  32. bw.Write((short)(obj.transform.localScale.y * 100.0f));
  33. bw.Write((short)(obj.transform.localScale.z * 100.0f));
  34. }
  35. }
  36. }
  37. }
  38. bw.Flush();
  39. bw.Close();
  40. fs.Close();
  41. }
csharp
运行

注解

在写入二进制数据时用到的核心类就是BinaryWriter ,Binary是二进制的意思 ,可见操作二进制写入就用BinaryWriter了。 常用的数据类型会分配固定的字节数量,假设BinaryWriter 写入一个short 那么就占2字节,写一个 int 就占4字节,如果是数组的话需要数组类型字节长度在乘以数组长度。

byte:一个字节(8位) 
short:两个字节(16位) 
int:四个字节(32位)(一个字长) 
long:八个字节(64位)
float:四个字节(32位)
double:八个字节(64位)

然后在说说string,字符串它并不是标准的数据类型,它是一个对象 object 那么它的字节长度就是可变的。开始我也在string 上纠结了一小会儿。还有BinaryWriter 在写入string 的时候会现将字符串的长度以byte的形式储存,然后在储存字符串的字节长度。那么在解析字符串的时候需要先解析字符串长度,然后在根据长度取得后面对应长度的字节数组,再把这个字节数组转换成string就行啦。还有,上面我用的是short x 100 其实上为了节省长度, 因为short是2字节,float是4字节。我在解析的时候用short 在除以100 就可以 换算成float拉。

然后我们在看看解析的代码,写入的时候我们用的是BinaryWriter 那么读取的时候应该是 BinaryReader。

Binary.cs

  1. using UnityEngine;
  2. using System.Collections;
  3. using System.IO;
  4. using System.Text;
  5. using System;
  6. public class Binary : MonoBehaviour
  7. {
  8. void Start ()
  9. {
  10. string filepath = Application.dataPath + @"/StreamingAssets/binary.txt";
  11. if(File.Exists (filepath))
  12. {
  13. FileStream fs = new FileStream (filepath,FileMode.Open);
  14. BinaryReader br = new BinaryReader(fs);
  15. int index = 0;
  16. //将二进制字节流全部读取在这个byte数组当中
  17. //ReadBytes传递的参数是一个长度,也就是流的长度
  18. byte[] tempall = br.ReadBytes((int)fs.Length);
  19. //开始解析这个字节数组
  20. while(true)
  21. {
  22. //当超过流长度,跳出循环
  23. if(index >= tempall.Length)
  24. {
  25. break;
  26. }
  27. //得到第一个byte 也就是得到字符串的长度
  28. int scenelength = tempall[index];
  29. byte []sceneName = new byte [scenelength];
  30. index += 1;
  31. //根据长度拷贝出对应长度的字节数组
  32. System.Array.Copy(tempall,index,sceneName,0,sceneName.Length);
  33. //然后把字节数组对应转换成字符串
  34. string sname = System.Text.Encoding.Default.GetString(sceneName);
  35. //这里和上面原理一样就不赘述
  36. int objectLength = tempall[index + sceneName.Length];
  37. byte []objectName = new byte [objectLength];
  38. index += sceneName.Length + 1;
  39. System.Array.Copy(tempall,index,objectName,0,objectName.Length);
  40. string oname = System.Text.Encoding.Default.GetString(objectName);
  41. //下面就是拿short 每一个short的长度是2字节。
  42. index += objectName.Length;
  43. byte[] posx = new byte[2];
  44. System.Array.Copy(tempall,index,posx,0,posx.Length);
  45. //取得对应的数值 然后 除以100 就是float拉。
  46. float x = System.BitConverter.ToInt16(posx,0) /100.0f;
  47. //下面都差不多
  48. index += posx.Length;
  49. byte[] posy = new byte[2];
  50. System.Array.Copy(tempall,index,posy,0,posy.Length);
  51. float y = System.BitConverter.ToInt16(posy,0) /100.0f;
  52. index += posy.Length;
  53. byte[] posz = new byte[2];
  54. System.Array.Copy(tempall,index,posz,0,posz.Length);
  55. float z = System.BitConverter.ToInt16(posz,0) /100.0f;
  56. index += posz.Length;
  57. byte[] rotx = new byte[2];
  58. System.Array.Copy(tempall,index,rotx,0,rotx.Length);
  59. float rx = System.BitConverter.ToInt16(rotx,0) /100.0f;
  60. index += rotx.Length;
  61. byte[] roty = new byte[2];
  62. System.Array.Copy(tempall,index,roty,0,roty.Length);
  63. float ry = System.BitConverter.ToInt16(roty,0) /100.0f;
  64. index += roty.Length;
  65. byte[] rotz = new byte[2];
  66. System.Array.Copy(tempall,index,rotz,0,rotz.Length);
  67. float rz = System.BitConverter.ToInt16(rotz,0) /100.0f;
  68. index += rotz.Length;
  69. byte[] scax = new byte[2];
  70. System.Array.Copy(tempall,index,scax,0,scax.Length);
  71. float sx = System.BitConverter.ToInt16(scax,0) /100.0f;
  72. index += scax.Length;
  73. byte[] scay = new byte[2];
  74. System.Array.Copy(tempall,index,scay,0,scay.Length);
  75. float sy = System.BitConverter.ToInt16(scay,0) /100.0f;
  76. index += scay.Length;
  77. byte[] scaz = new byte[2];
  78. System.Array.Copy(tempall,index,scaz,0,scaz.Length);
  79. float sz = System.BitConverter.ToInt16(scaz,0) /100.0f;
  80. index+=scaz.Length;
  81. if(sname.Equals("Assets/StarTrooper.unity"))
  82. {
  83. //最后在这里把场景生成出来
  84. string asset = "Prefab/" + oname;
  85. Vector3 pos = new Vector3 (x,y,z);
  86. Vector3 rot = new Vector3(rx,ry,rz);
  87. Vector3 sca = new Vector3(sx,sy,sz);
  88. GameObject ob = (GameObject)Instantiate(Resources.Load(asset),pos,Quaternion.Euler(rot));
  89. ob.transform.localScale = sca;
  90. }
  91. }
  92. }
  93. }
  94. // Update is called once per frame
  95. void Update ()
  96. {
  97. }
  98. }
csharp
运行
运行一下,场景依然生成的非常完美,在处理二进制解析的时候需要特别注意的就是字节对齐,因为你的所有数据其实就是一个byte[]字节数组,需要有理有序的把字节数组拆分,然后在转换成对应的数据,所以一定要对齐不然肯定会出错的。


最后把代码放出来,晚安 Good Ngith 哇咔咔。

下载地址 :http://vdisk.weibo.com/s/la_QE 

 

留言中刚好有人讨论到这块。另外还有一种方式也可以实现动态增加建立场景,使用.unity 来实现场景的加载,我觉得这种方式可能会更好一些。我在网上已经发现有人写了,那就转载过来吧。

原文地址:http://blog.csdn.net/cony100/article/details/8842919

在Unity3d中,场景(scene)多半通过在build settings中点击add current或者把场景拖进面板实现,假如不这么做,你的场景便不会被加载,哪怕你制定了绝对路径。

就是说,一个游戏里要加载多少场景多半都是固定的。

这样的方法会有很多不便,不容易动态加载场景。所以我们今天要说的,是一种动态加载场景的方法。

首先,你需要一个编辑器文件,放在editor文件夹下。注意,这个文件不可以继承自monobehaviour

  1. public class BuildSceneEditor{
  2. [@MenuItem("build/BuildWebplayerStreamed")]
  3. static void Build(){
  4. string[] levels = new string[]{"Assets/Level1.unity","Assets/Level2.unity"};
  5. BuildPipeline.BuildStreamedSceneAssetBundle(levels,"streamed.unity3d",BuildTarget.WebPlayer);
  6. }
  7. }
csharp
运行
这样,在你的unity编辑器上出现了一个按钮,你执行这个按钮,则会在你的Assets同级目录下出现你build好的streamed.unity3d文件,你把这个文件放在服务器上,下面一步就是下载这个文件并build了。

  1. WWW download = WWW.LoadFromCacheOrDownload("http://xxx/streamed.unity3d",0);
  2. yield return download;
  3. Application.LoadLevel("Level1");
csharp
运行

大家注意到了吗。下载好以后就可以直接loadlevel了,不需要手动进行add current的操作了。

这里还有一篇圣典翻译的文章 http://game.ceeger.com/Script/BuildPipeline/BuildPipeline.BuildStreamedSceneAssetBundle.html

     最后我在补充一下使用.unity3d确实方便很多,因为它不仅会把场景打包进去,并且还会把场景中对应的资源文件打包进去。举个例子,你将美工做好的模型文件放在Project视图中,然后在将模型放在Hierarchy视图中的 100,100,100坐标点中,最后把该场景打包成.unity3d文件。此时你在新建一个工程只需下载刚刚打包的场景文件,他会自动把模型放在 100,100,100坐标点中。

      这说明场景文件,包含了该场景中所用到的所有模型,并且还包含了模型资源与Hierarchy视图的关系。它会带来一个弊端,比如你有N个场景,每个场景中都有相同的模型文件,这样每个场景都需要重复下载这些相同的模型文件,所以我觉得最好还是使用assetbundle来对同类的资源文件进行分包处理。




免责声明:本文系网络转载或改编,未找到原创作者,版权归原作者所有。如涉及版权,请联系删
相关文章
QR Code
微信扫一扫,欢迎咨询~

联系我们
武汉格发信息技术有限公司
湖北省武汉市经开区科技园西路6号103孵化器
电话:155-2731-8020 座机:027-59821821
邮件:tanzw@gofarlic.com
Copyright © 2023 Gofarsoft Co.,Ltd. 保留所有权利
遇到许可问题?该如何解决!?
评估许可证实际采购量? 
不清楚软件许可证使用数据? 
收到软件厂商律师函!?  
想要少购买点许可证,节省费用? 
收到软件厂商侵权通告!?  
有正版license,但许可证不够用,需要新购? 
联系方式 155-2731-8020
预留信息,一起解决您的问题
* 姓名:
* 手机:

* 公司名称:

姓名不为空

手机不正确

公司不为空