Unity实际开发中,一般会有很多个场景,不可能每次都在setting里加场景号,我们需要动态加载。一般的做法是把这些场景做成一个一个prefab,再把场景信息保存起来。然后切换场景的时候切到一个预先保持的空场景里 保存一个空的场景,在加载之前保持的prefab,在对场景信息赋值。这里的场景信息可能包括渲染设置,lightmap等内容。这时候需要把这些场景信息保存起来。在c#中很容易对一些数据序列化。
一.用c#的BinaryFormatter对数据进行二进制序列化
例:
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization;
[Serializable] //自定义的类一定要加这个特性
public class Person
{
public string name = "";
public int age = 0;
}
public class Test
{
static List m_persons = new List();
static void init()
{
for (int i = 0; i < 100; i++)
{
Person p = new Person();
p.name = "test"+i;
p.age = i;
m_persons.Add(p);
}
}
//序列化
static void serialize()
{
FileStream writer = new FileStream("./data.dat", FileMode.Create);
try
{
BinaryFormatter binaryFormat = new BinaryFormatter();
binaryFormat.Serialize(writer, m_persons);
}
catch (SerializationException e)
{
ClientLog.LogError("Failed to serilize. " + e.Message);
}
finally
{
writer.Close();
}
}
//反序列化
static void deserialize()
{
List listData = null;
FileStream reader = new FileStream("./data.dat", FileMode.Open);
try
{
BinaryFormatter binaryFormat = new BinaryFormatter();
listData = (List)binaryFormat.Deserialize(reader);
}
catch (SerializationException e)
{
ClientLog.LogError("Failed to Deserialize:" + e.Message);
}
finally
{
reader.Close();
}
}
}
上面的方法可以序列化自定义类型的数据,而且像List、Dictionary这种实现了ISerializable接口的都可以用这种方法序列化。但在unity中这不是最好的方法。
二.用unity的ScriptableObject序列化
这种方法,unity的一些类型以及c#的基础类型都可以序列化,因此在unity中建议用这种方法。
例如自定义数据类型如下(注意:要序列化的类型一定要继承ScriptableObject,一定要放在单独的文件里):
public class Test : ScriptableObject
{
public string name = "this is a test!";
[Serializable] //自定义的类一定要加这个特性
public class T
{
public Vector4 m_v = new Vector4(1.0f, 1.0f, 1.0f, 1.0f);
}
public T m_t;
}
然后再unity添加菜单选项:
[MenuItem("Tools/Save Data")]
static public void SerializeData()
{
Test test = ScriptableObject.CreateInstance();
string destPath = "Assets/StreamingAssets/test.asset";
AssetDatabase.CreateAsset(test, destPath); //生成序列化数据
AssetDatabase.Refresh();
Object o = AssetDatabase.LoadAssetAtPath(destPath, typeof(LightmapInfo));
string bundlePath = "Assets/StreamingAssets/test.bundle";
BuildPipeline.BuildAssetBundle(o, null, bundlePath, BuildAssetBundleOptions.CompleteAssets | BuildAssetBundleOptions.CollectDependencies, BuildTarget.StandaloneWindow);
AssetDatabase.DeleteAsset(destPath);
}
生成序列化数据,然后打成bundle包就可以用WWW加载了。
反序列化如下:
IEnumerator DeserializeData()
{
string bundlePath = "Assets/StreamingAssets/test.bundle";
WWW www = new WWW(bundlePath);
yield return www;
Test test = assetBundle.mainAsset as Test;
Debug.Log(test.name);
Debug.Log(test.m_t.x);
}