常常看说序列化,说什么发消息要序列化,存数据也需要序列化。今天就看了看这个到底是什么东西。
是什么
序列化是将对象状态转换为可保持或传输的格式的过程。与序列化相对的是反序列化,它将流转换为对象。这两个过程结合起来,可以轻松地存储和传输数据。简单的说就是把对象转换成字节然后到内存中,数据库中或者是文件中的一个过程。
再通俗点讲就是学习武功时候,师傅给徒弟说武功口诀这个过程,然后徒弟把武功口诀一招一式练成就是反序列化。
在Unity中过程
大概知道序列化是什么东西了,我们来看看他在unity中是怎么样的。
不知道你们遇到过这种情况没有,就是在运行unity时,你去更改一些组件的变量,然后停止运行,再去看你所更改的变量又还原到了你运行之前没有更改的那个数值了。其实这个就是unity序列化的特性吧。
这个是因为unity其实是两层,C++层与unity控制层,因为unity是用c++编写的,但是我们自己编写的脚本是c#,就会有一个交互。当我们点击运行按钮时,先是把所有的序列化数据在内部创建,然后把他们存在c++这一层;然后清除unity控制层这边所有的内存和消息;然后加载我们编写的脚本;最后再把c++层中存储的序列化数据反序列化到unity控制层中去。
所以我们在运行时更改组件上的变量其实是没有用的,因为我仅仅是更改unity控制层上的数据,正真数据是从c++层读取出来的。
在Unity中使用
在unity系统中用到序列化的有Inspector面板,预制物体,实例化物体,场景存储,加载场景,代码的编译等等,可以看看这个文章讲很清楚他们是怎么在系统中用序列化的。
在脚本使用只需要序列化的类名前面加上 [Serializable]即可,加上System命名空间。
[Serializable]
class Animal
{
public string name;
}
class MyScript : MonoBehaviour
{
public Animal[] animals;
}
这个写法可以把类中公共变量做序列化,私有变量需要序列化需要加上[SerializeField],公共变量不想被序列化加上 [NonSerializable]就可以了。当然静态(static),常量(const),只读(readonly)的变量,抽象类这些是不能被序列化的。
二进制序列化简单例子
数据类:
[Serializable]
public class MyTest
{
public int age;
public string name;
public override string ToString()
{
return String.Format("Age: {0}, Name: {1}", age, name);
}
}
操作:
public void OnGUI()
{
if (GUILayout.Button("Save"))
{
var file = File.Open(Application.dataPath + "/myTest.dat", FileMode.OpenOrCreate);
var bf = new BinaryFormatter();
var myTest = new MyTest {age = 2, name = "ben"};
bf.Serialize(file, myTest);
file.Close();
}
if (GUILayout.Button("Load"))
{
if (File.Exists(Application.dataPath + "/myTest.dat"))
{
var file = File.Open(Application.dataPath + "/myTest.dat", FileMode.Open);
var bf = new BinaryFormatter();
var myTest = (MyTest) bf.Deserialize(file);
file.Close();
Debug.Log(myTest.ToString());
}
}
}
当然序列化在unity中也又不足,像什么不支持多态什么的,在上面的那个文章上也讲了的,我就不翻译了。差不多就说这么多吧,这些就是我自己对序列化的一些理解吧,有什么说的不对,咱们都可以讨论哦~