[Unity3D]用ScriptableObject打包数据


简介

开发人员一般通过BuildPipeline函数去打包文件,然后通过WWW去下载

但是BuildPipeline打包的对象类型是有限制的,像GameObject,TextAsset这些文件是可以直接打包的,但是,如果要读取一些Unity不支持的类型,我们就需要用到ScriptableObject了。这里用打包Csv表作为例子示例一下


实现

1. 编辑ScriptObject对象

首先,csv表的内容就是一段字符串,又或者说是一段bytes,看程序需求,我这里把csv表的内容当成一段bytes读取,吧

所以,csv表的ScriptableObject可以这样写

[csharp]  view plain copy
  1. using UnityEngine;  
  2. using System.Collections;  
  3.   
  4. public class soCsv : ScriptableObject  
  5. {  
  6.     public string fileName;  
  7.     public byte[] content;  
  8. }  

2. 打包文件

    有了Csv的ScriptableObject后,就可以开始写打包函数了

简单说一下流程:

1.获取选中的csv表对象

2.赋值到刚声明的csv表对应的ScriptableObject

3.用该ScriptableObject生成Asset

4.读取生成的Asset后打包(生成与读取asset的过程有点别扭,但只有这样获得的Object对象,才能打包成功...)

[csharp]  view plain copy
  1. using UnityEngine;  
  2. using System.Collections;  
  3. using UnityEditor;  
  4. using System.IO;  
  5. using System.Collections.Generic;  
  6.   
  7.   
  8. public class BuildTest : MonoBehaviour   
  9. {  
  10.     [MenuItem("Assets/Build Csv")]  
  11.     static void BuildCsv()  
  12.     {   
  13.         string applicationPath = Application.dataPath;  
  14.         string saveDir = applicationPath + "/Resources_out/";  
  15.         string savaPath = saveDir + "csv.unity3d";  
  16.   
  17.         //获取选中的对象  
  18.         /*关于SelectionMode参数,目前我只用过Assets,DeepAssets,其他的暂且不说 
  19.          Assets:获取当前选中的单一对象 
  20.          DeepAssets:获取当前选中的对象,如果选中的文件夹,则会获取到文件夹的子对象 
  21.          *  
  22.          *  
  23.         Unfiltered  : Return the whole selection. 
  24.         TopLevel :   Only return the topmost selected transform. A selected child of another selected transform will be filtered out. 
  25.         Deep:    Return the selection and all child transforms of the selection. 
  26.         ExcludePrefab   : Excludes any prefabs from the selection. 
  27.         Editable     :Excludes any objects which shall not be modified. 
  28.         Assets   :Only return objects that are assets in the Asset directory. 
  29.         DeepAssets  : If the selection contains folders, also include all assets and subfolders within that folder in the file hierarchy. 
  30.          *  
  31.          */  
  32.   
  33.         Object[] selections = Selection.GetFiltered(typeof(Object), SelectionMode.DeepAssets);  
  34.         List outs = new List();  
  35.         for (int i=0,max=selections.Length; i
  36.         {  
  37.             Object obj = selections[i];  
  38.             //asset path  : 相对Asset目录  
  39.             string fileAssetPath = AssetDatabase.GetAssetPath(obj);  
  40.             //判断后缀  
  41.             if (fileAssetPath.Substring(fileAssetPath.LastIndexOf('.') + 1) != "csv")  
  42.                 continue;  
  43.   
  44.             //  
  45.             string fileWholePath = applicationPath + "/" + fileAssetPath.Substring(fileAssetPath.IndexOf("/"));  
  46.   
  47.             //  
  48.             soCsv csv = ScriptableObject.CreateInstance();  
  49.             csv.fileName = obj.name;  
  50.             csv.content = File.ReadAllBytes(fileWholePath);  
  51.   
  52.             //这一个存与读的步骤是否必要的?  
  53.             string assetPathTemp = "Assets/Resources_Local/Temp/" + obj.name + ".asset";  
  54.             AssetDatabase.CreateAsset(csv, assetPathTemp);  
  55.   
  56.             Object outObj = AssetDatabase.LoadAssetAtPath(assetPathTemp, typeof(soCsv));  
  57.   
  58.             //  
  59.             Debug.Log("package : " + outObj.name);  
  60.             outs.Add(outObj);  
  61.         }  
  62.   
  63.         //  
  64.         Object[] outObjs = outs.ToArray();  
  65.         if (BuildPipeline.BuildAssetBundle(null, outs.ToArray(), savaPath))  
  66.             Debug.Log("build " + savaPath + " success,length = " + outObjs.Length);  
  67.         else  
  68.             Debug.LogWarning("build " + savaPath + " failed");  
  69.     }  
  70.   
  71. }  

  72. 3. 下载并解析内容

    [csharp]  view plain copy
    1. using UnityEngine;  
    2. using System.Collections;  
    3. using System.IO;  
    4.   
    5. using LumenWorks.Framework.IO.Csv;  
    6.   
    7. public class Test : MonoBehaviour {  
    8.   
    9.     WWW w;  
    10.     string path ;  
    11.     void Start () {  
    12.         //File协议主要用于访问本地计算机中的文件,所以这里还需要加file:///  
    13.         path = "file:///" + Application.dataPath + "/Resources_out/csv.unity3d";  
    14.         w = new WWW(path);  
    15.     }  
    16.       
    17.     // Update is called once per frame  
    18.     void Update () {  
    19.         if (w != null)  
    20.         {  
    21.             if (w.isDone)  
    22.             {  
    23.                 Debug.Log("download " + path);  
    24.   
    25.                 Debug.Log(w.assetBundle.mainAsset);  
    26.   
    27.                 /*loadall的参数如果不指定类型,很可能会读取到额外的内容 
    28.                  * 像我测试的时候,就发现一直多出了一个名字叫soCsv的对象 
    29.                  * 最好还是指定一下类型 
    30.                  * */  
    31.                 Object[] objs = w.assetBundle.LoadAll(typeof(soCsv));  
    32.                 Debug.Log("count : " + objs.Length);  
    33.                 for (int i = 0, max = objs.Length; i < max; i++)  
    34.                 {  
    35.                     Object obj = objs[i];  
    36.                     soCsv csv= obj as soCsv;  
    37.   
    38.                     //用string表做一个例子吧  
    39.                     if (csv.fileName != "string")  
    40.                     {  
    41.                         continue;  
    42.                     }  
    43.   
    44.                     //  
    45.                     MemoryStream ms = new MemoryStream(csv.content);  
    46.                     if (ms == null)  
    47.                     {  
    48.                         Debug.LogWarning("转换csv失败");  
    49.                         continue;  
    50.                     }  
    51.   
    52.                     StreamReader sr = new StreamReader(ms);  
    53.                     TextReader tr = sr as TextReader;  
    54.                     if (tr == null)  
    55.                     {  
    56.                         Debug.LogWarning("text reader is null");  
    57.                         continue;  
    58.                     }  
    59.   
    60.                     CsvReader cr = new CsvReader(tr, true);  
    61.                     if (cr == null)  
    62.                     {  
    63.                         Debug.LogWarning("CsvReader is null");  
    64.                         continue;  
    65.                     }  
    66.   
    67.                     //将字段头输出  
    68.                     string[] headers = cr.GetFieldHeaders();  
    69.                     foreach (string szHeader in headers)  
    70.                         Debug.Log(szHeader);  
    71.   
    72.                       
    73.                 }  
    74.   
    75.                 w = null;  
    76.             }  
    77.         }  
    78.     }  
    79. }  

    你可能感兴趣的:(配置)