Unity3D中序列化字段常使用[SerializeField],序列化类常采用[System.Serializable],非序列化采用[System.NonSerialized]。
序列化类使用时发现一些区别。测试如下:
(1)
将脚本第一次拖拽到场景中后,运行程序。发现,对类进行序列化后,id,name会保持在代码中写的字段值。
如果我们退出运行,对检视面板的值进行修改,再运行,如下图所示。那么会始终运行检视面板中修改的值!
如果我们退出运行,对代码中的值进行修改,再运行,如下图所示。那么发现print的值还是运行检视面板中的值!如下图所示:
由此可见,序列化类后,显示的数值由检视面板的值确定。脚本中的数值只是在第一次拖拽脚本到游戏对象时有用。
套用C#书上的一句话:序列化又称串行化,是.NET运行时环境用来支持用户定义类型的流化的机制。其目的是以某种存储形成使自定义对象持久化,或者将这种对象从一个地方传输到另一个地方。
如果不想序列化某个类的字段,有两种方式:第一个就是可以用System.NonSerialized。增加了这个属性的字段不会在检视面板中显示。如下:
第二个方式就是将字段的访问修饰符设置为private或protected即可,如下所示,由于字段为私有或保护,只能在类内或派生的类中访问。这里采用属性getname获取name的值,并print。
一开始我把public ClassToSerialize classSerialize = new ClassToSerialize();的new部分放在Start()中,这时,不管有没有[Serializable],数值都会以类中写入的初始值决定。原因就是:Start()在字段赋予初始值之后运行的。如下所示:
没有运行时,修改id数值:
运行后:
1 using UnityEngine; 2 using System.Collections; 3 using System; 4 5 public class test : MonoBehaviour { 6 public ClassToSerialize classSerialize;// = new ClassToSerialize() 7 void Start () { 8 classSerialize = new ClassToSerialize();//这里实例化 9 print(classSerialize.id + classSerialize.getname); 10 } 11 } 12 13 [Serializable] 14 public class ClassToSerialize 15 { 16 public int id = 120; 17 // [NonSerialized] 18 protected string name = "tongtong1989"; 19 public string getname 20 { 21 get { return name; } 22 } 23 }
当然,您也可以不在Start()中实例化,因为已经Serializable了,如下所示:
不过,您不可以把[Serializable]也注释掉,那样的话,类就不能序列化,默认初始化为null,调用字段会提示空引用异常!如下: