在Unity3D中使用ScriptableObject进行序列化

ScriptableObject类型经常用于存储一些unity3d本身不可以打包的一些object,比如字符串,一些类对象等。用这个类型的子类型,则可以用BuildPipeline打包成assetbundle包供后续使用,非常方便。这样除了playerpref和c#文件读取外,另外的一种存取一些数据对象的方法

[csharp]   view plain copy print ?
  1. using UnityEngine;   
  2.   
  3. public class XMLContains : ScriptableObject   
  4.   
  5. {   
  6.   
  7.     public string theXML;   
  8.   
  9. }   



By making your class enherit from ScriptableObject, it becomes an "Asset Type" to unity, in the sense that you can store them on disk, and use the Unity IDE interface to drag it from the assetsfolder to a behaviour or whatever. It also automatically plays nice with Unity's dependency tracking system that decides what does and what does not go into a webplayer. Going a bit further with this example, you could have let's say a TieFighter class, actually get some of its information (max health, max speed, acceleration), from your xml file, by making the TieFighter class look like this:
 

[csharp]   view plain copy print ?
  1. using UnityEngine;   
  2.   
  3. public class TieFighter : MonoBehaviour   
  4.   
  5. {   
  6.   
  7.      public XMLContainer myXMLSettings;   
  8.   
  9.    
  10.   
  11.      void Awake()   
  12.   
  13.      {   
  14.   
  15.         //parse myXMLSettings.theXML into reasonable data   
  16.   
  17.      }   
  18.   
  19.    
  20.   
  21.      void Update()   
  22.   
  23.      {   
  24.   
  25.         //use the reasonable data   
  26.   
  27.      }   
  28.   
  29.  }  


 

You could then attach the TieFighter script to a gameobject, and then drag your xml-asset from your assetsfolder onto the myXMLSettings public field.Please note that this example is much better at showing how you could use a ScriptableObject than how to properly implement a TieFighter, as I would never really have that parse an actual xml file on runtime. Tiefighters are too cool for xml anyway.
以上是不做成bundle包的形式,下面提供了一种打包成bundle资源,通过www来进行载入的方案:

通常,可以用BuildPipeline.BuildAssetBundle打包资源,这些资源包括模型、纹理、贴图等。其实也可以打包ScriptableObject,而ScriptableObject中可以存储任何数据类型。

以下为一个完整示例。

 

1、先创建一个类:

[csharp]   view plain copy print ?
  1. using UnityEngine;   
  2.   
  3. using System.Collections.Generic;    
  4.   
  5. public class SysData : ScriptableObject   
  6.   
  7. {                 
  8.   
  9. public List<Vector3> content;   
  10.   
  11. }  


 

该类只有一个属性content。当然也可以声明更多属性、事件和方法。

在后面,这个类的实例将作为资源被打包。

 

2、创建一个编辑器脚本:

该脚本用于实例化SysData,设置一些数据,然后打包。

 

[csharp]   view plain copy print ?
  1. using UnityEngine;   
  2.   
  3. using UnityEditor;   
  4.   
  5. using System.Collections.Generic;    
  6.   
  7. public class Export  
  8.   
  9. {          
  10.   
  11.   [MenuItem("Assets/Export")]           
  12.   
  13.   public static void Execute()   
  14.   
  15.   {                
  16.   
  17.    //实例化SysData               
  18.   
  19.    SysData sd = ScriptableObject.CreateInstance<SysData>();                             
  20.   
  21.     //随便设置一些数据给content                 
  22.   
  23.     sd.content = new List<Vector3>();                 
  24.   
  25.     sd.content.Add(new Vector3(1,2,3));                 
  26.   
  27.     sd.content.Add(new Vector3(4,5,6));                              
  28.   
  29.     // SysData将创建为一个对象,这时在project面板上会看到这个对象。                 
  30.   
  31.     string p = "Assets/SysData.asset";           
  32.   
  33.     AssetDatabase.CreateAsset(sd, p);                 
  34.   
  35.     Object o = AssetDatabase.LoadAssetAtPath(p, typeof(SysData));                              
  36.   
  37.     //打包为SysData.assetbundle文件。                 
  38.   
  39.     BuildPipeline.BuildAssetBundle(o, null"SysData.assetbundle");                 
  40.   
  41.     //删除面板上的那个临时对象               
  42.   
  43.      AssetDatabase.DeleteAsset(p);                        
  44.   
  45.   }   
  46.   
  47. }   
  48.   
  49.    

 

3、运行时加载这个数据资源。

[csharp]   view plain copy print ?
  1. IEnumerator Start ()   
  2. {                
  3.  WWW www = new WWW("file://" + Application.dataPath + "/../SysData.assetbundle");                
  4.  yield return www;    
  5.                
  6.  //转换资源为SysData,这个sd对象将拥有原来在编辑器中设置的数据。                
  7.  SysData sd = www.assetBundle.mainAsset as SysData;   
  8.  //如打印sd.content[0],将得到Vector3(1,2,3);               
  9.  print(sd.content[0]);  
  10. }  


 

4、这其实是把整个对象实例打包,如果ScriptableObject属性中包括其他的类实例,则这些类需加上[Serializable]序列化。通过这种方法,可以将系统需要的数据(如角色分类、matrix4x4数据等等)打包,加载后直接转换为预定的类型,具有更高的效率。

你可能感兴趣的:(unity3d)