unity存储数值文件的方式有很多,目前常用的有xml,csv,json等,xml与json都是节点式,csv的话策划可直接在excel导出,相对方便一些,目前对这三种方式的性能消耗未作探究,目前公司项目使用的csv表格存储数值,所以暂时仅讨论如何用序列化的方式优化数据资源加载,对于本文未提及的部分,欢迎朋友们补充~

首先了解序列化,序列化就是将资源文件转换成二进制文件到某个文件夹内,这个过程只需一次,然后在运行或者游戏发布以后加载数据资源时就可以直接将二进制文件夹内的二进制资源反序列化,结果就跟load数据资源相同,但这么读取二进制文件将极大的提升加载速度,废话不多说,先看一个小的例子:

首先想要序列化需要引用

using System.IO;
 using System.Runtime.Serialization.Formatters.Binary;
 using System.Runtime.Serialization;

第三个是需要抛出异常时引用,然后创建一个类,相当于后面的csv表格文件

[Serializable]
     public class ClassToSerialize
     {
         public int id = 1;
         public string name = "jack";
         public string Sex = "man";
     }

记住要想序列化某一个数据类型,一定要在前面加上 [Serializable]

开始序列化

public void SerializeNow()
     {
         ClassToSerialize c = new ClassToSerialize();
         string path = Application.streamingAssetsPath + "/test.dat";
         FileStream fs = new FileStream(path, FileMode.Create);
         BinaryFormatter formatter = new BinaryFormatter();
         try
         {
             formatter.Serialize(fs, c);
         }
         catch (SerializationException e)
         {
             Debug.Log("Failed to serialize. Reason: " + e.Message);
             throw;
         }
         finally
         {
             fs.Close();
        }

注意path路径,Application.streamingAssetsPath为StreamingAssets文件夹的本地路径,因此在序列化之前先在Unity工程的Assets目录下创建一个StreamingAssets文件夹,名称一定要是StreamingAssets,序列化后ClassToSerialize里的内容就存储在了test.dat文件内

序列化成功了,然后开始反序列化使用

IEnumerator DeSerializeNow()
     {
         
         ClassToSerialize c = new ClassToSerialize();        string path = Application.streamingAssetsPath + "/test.dat";
         //FileStream fs = File.Create(filename);
         //FileInfo info = new FileInfo(filename);
         //if (!info.Exists)
         //{
         //    SerializeNow();    
         //}
         FileStream fs = new FileStream(path, FileMode.Open);
         yield return 0;
         try
         {
             BinaryFormatter formatter = new BinaryFormatter();
             c = formatter.Deserialize(fs) as ClassToSerialize;
         }
         catch (SerializationException e)
         {
             Debug.Log("Failed to deserialize. Reason: " + e.Message);
             throw;
         }
         finally
         {
             fs.Close();
         }
         textLab.text = c.name;
     }

这样就可以讲二进制文件中的内容反序化回c身上了,为了更加直观的展示,添加以下代码

void OnGUI() 
     {
         if (GUI.Button(new Rect(0,0,100,100),"点我序列化"))
         {
              SerializeNow();
         }
         if (GUI.Button(new Rect(0, 150, 100, 100), "点我反序列化"))
         {
             StartCoroutine(DeSerializeNow());
         }
         //if (GUI.Button(new Rect(0, 300, 100, 100), "点我打印路径"))
         //{
         //    ShowThePath();
         //}
     }

序列化只需在unity里运行一次

也许有朋友注意到了,在DeSerializeNow方法里我使用了携程,这里提到一个坑,windows平台下使用filestream读取二进制文件无任何问题,但发布到安卓平台是会报错找不到文件,开始我以为是路径不正确,但反复调试之后确定了是filestream在安卓平台下无法直接读取二进制文件,因此为了可以在安卓平台下反序列化,将DeSerializeNow修改为:

IEnumerator DeSerializeNow()
     {
         
         ClassToSerialize c = new ClassToSerialize();        string path = Application.streamingAssetsPath + "/test.dat";
         //FileStream fs = File.Create(filename);
         //FileInfo info = new FileInfo(filename);
         //if (!info.Exists)
         //{
         //    SerializeNow();    
         //}
         if (Application.platform == RuntimePlatform.WindowsEditor)
         {
             FileStream fs = new FileStream(path, FileMode.Open);
             yield return 0;
             BinaryFormatter formatter = new BinaryFormatter();
             c = formatter.Deserialize(fs) as ClassToSerialize;
             fs.Close();
         }
         else if(Application.platform == RuntimePlatform.Android)
         {
             WWW www = new WWW(path);
             yield return www;
             MemoryStream fs = new MemoryStream(www.bytes);
             BinaryFormatter formatter = new BinaryFormatter();
             c = formatter.Deserialize(fs) as ClassToSerialize;
             fs.Close();
         }
         textLab.text = c.name;
     }

如果有朋友想在安卓手机上序列化的话, Application.streamingAssetsPath就不行了,如果谁有可行的方法欢迎讲解,我目前所能发现的可以在安卓平台上序列化的路径就是Application.persistentDataPath,这个路径位置就不是在工程目录下了,他是每个平台的data存储路径,想知道的朋友可以自己打印出来看