Unity序列化和持久化

据我所知unity Serialization对于基本数据类型非常好用,但处理复类型时就有些基础缺陷了。

我的需求是连接组件和文件并永久保存这种关系。而组件(或游戏对象)的InstanceID不管用,因为每次场景加载都会不一样。

Unity内置的持久化策略是通过“m_LocalIdentfierInFile”(将检视面板视图切换为Debug模式即可看到该字段)来连接场景文件和游戏对象及其组件的(这个肯定是Unity的拼写错误,应该是Identifier,当然它也没有要改正的倾向)。

所以我也可以利用这个字段来做些什么啊。但最大的难题是UnityEngine没有提供任何可以使用该字段的接口,也没说明要如何用,几番查证得知这是在引擎的C++端实现的。

废话少说,多方尝试之后最后想出了一个简单的解决办法,就是在编辑器中复制一份“m_LocalIdentfierInFile”,并将其保存为序列化的属性。

但是,它对于运行时创建的游戏对象或组件并不管用。

下面是实现方法  :

  1. // This is a copy of the "m_localIndentiferInFile"
  2. // (don‘t forget to use [Serializable] on the class)
  3. [SerializeField]
  4. private int persistentID = -1;

复制代码

结合下面这段代码就可以访问“m_LocalIdentfierInFile”了,确保该段代码添加了编辑器预定义宏(#ifdef UNITY_EDITOR),并且不要引用UnityEditor命名空间,否则会导致编译失败。

  1. // Init this instance, it‘s public so it can be called from a InspectorScript
  2. // is only set via the unity editor
  3. public void init ()
  4. {
  5. #if UNITY_EDITOR
  6. PropertyInfo inspectorModeInfo =
  7. typeof(UnityEditor.SerializedObject).GetProperty ("inspectorMode",
  8. BindingFlags.NonPublic | BindingFlags.Instance);
  9. UnityEditor.SerializedObject serializedObject =
  10. new UnityEditor.SerializedObject (comp);
  11. inspectorModeInfo.SetValue (serializedObject, UnityEditor.InspectorMode.Debug, null);
  12. UnityEditor.SerializedProperty localIdProp =
  13. serializedObject.FindProperty ("m_LocalIdentfierInFile")
  14. //Debug.Log ("found property: " + localIdProp.intValue);
  15. persistentID = localIdProp.intValue;
  16. //Important set the component to dirty so it won‘t be overriden from a prefab!
  17. UnityEditor.EditorUtility.SetDirty (this);
  18. #endif
  19. }

复制代码

上面的脚本最初由thelackey3326发布在Unity论坛中,最后加上一句“UnityEditor.EditorUtility.SetDirty (this);”,以防预制件persistentID被重写。

下面是在OnEnable()中调用init()方法:

  1. public void OnEnable ()
  2. {
  3. myPersist.init ();
  4. }

复制代码

这只在场景保存后有用(保存之前m_LocalIdentfierInFile == 0),在创建了游戏对象或拖拽预制件之后保存场景且至少点击一次游戏对象!

通常如果将预制件拖拽到场景中,就表示点击了它并进行了一些操作。

在场景即将保存时可以访问其中一些数据,Unity没有提供保存场景后进行访问的方法。下面的代码是在保存场景前调用init()函数:

  1. static string[] OnWillSaveAssets (string[] paths)
  2. {
  3. Object[] objs = Component.FindObjectsOfType (typeof(PersistObject));
  4. //Debug.Log ("OnWillSaveAssets " + objs.Length);
  5. foreach (Object obj in objs) {
  6. PersistObject persist = (PersistObject)obj;
  7. persist.init ();
  8. }
  9. return paths;
  10. }

复制代码

完整源码点此链接

以上代码表示,如果创建一个游戏对象,并使用编辑器获取“m_LocalIdentfierInFile”字段,就必须在此之后至少保存两次场景。第一次是让Unity设置“m_LocalIdentfierInFile”,第二次是将其保存到局部变量中。这并非最便捷的方法,但也够用了,只需使用持久化的游戏对象设置下场景就好。

原文地址:http://bbs.a-coder.cn/thread-8-1-1.html

时间: 2024-08-28 21:06:04

Unity序列化和持久化的相关文章

JAVA的序列化和持久化的区别与联系

持久化(Persistence) 即把数据(如内存中的对象)保存到可永久保存的存储设备中(如磁盘).持久化的主要应用是将内存中的对象存储在关系型的数据库中,当然也可以存储在磁盘文件中.XML数据文件中等等. 持久化是将程序数据在持久状态和瞬时状态间转换的机制. JDBC就是一种持久化机制.文件IO也是一种持久化机制. 持久化是一种对象服务,就是把内存中的对象保存到外存中,让以后能够取回.需要实现至少3个接口: void Save(object o) 把一个对象保存到外存中 Object Load

序列化和持久化 merge方法和saveOrUpdate方法

merge方法和saveOrUpdate方法的区别 merge方法是把我们提供的对象转变为托管状态的对象:而saveOrUpdate则是把我们提供的对象变成一个持久化对象:说的通俗一点就是:saveOrUpdate后的对象会纳入session的管理,对象的状态会跟数据库同步,再次查询该对象会直接从session中取,merge后的对 象不会纳入session的管理,再次查询该对象还是会从数据库中取. 使用merge方法修改时如果两次修改的值没有变,它只会执行select而不会进行update.

Unity 序列化 总结

查找了 Script Serialization http://docs.unity3d.com/Manual/script-Serialization.html 自定义序列化及例子: http://docs.unity3d.com/ScriptReference/ISerializationCallbackReceiver.OnBeforeSerialize.html 和Unity 圣典 在这博友 的基础上 再总结下Unity 的序列化 序列化的作用是: 可以显示变量(类,结构等)在inspe

序列化和持久化的区别

持久化(Persistence) 即把数据(如内存中的对象)保存到可永久保存的存储设备中(如磁盘).持久化的主要应用是将内存中的对象存储在关系型的数据库中,当然也可以存储在磁盘文件中.XML数据文件中等等. 持久化是将程序数据在持久状态和瞬时状态间转换的机制. JDBC就是一种持久化机制.文件IO也是一种持久化机制. 持久化是一种对象服务,就是把内存中的对象保存到外存中,让以后能够取回.需要实现至少3个接口: void Save(object o) 把一个对象保存到外存中 Object Load

数据的序列化,持久化,归档

数据的序列化,持久化,归档 1.Foundation 2.数据属性列表(NSArray,NSDictionary) 3.sqlite,cocodata 归档后文件的数据会自动加密,不再是明文,局限性在于,只能对一个对象进行归档 /**归档,数据持久化,数据序列化**/ /* NSString *filePath = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/text.arc"]; NSArray *arr

spark新能优化之序列化的持久化级别

除了对多次使用的RDD进行持久化操作之外,还可以进一步优化其性能.因为很有可能,RDD的数据是持久化到内存,或者磁盘中的.那么,此时,如果内存大小不是特别充足,完全可以使用序列化的持久化级别,比如MEMORY_ONLY_SER.MEMORY_AND_DISK_SER等.使用RDD.persist(StorageLevel.MEMORY_ONLY_SER)这样的语法即可. 这样的话,将数据序列化之后,再持久化,可以大大减小对内存的消耗.此外,数据量小了之后,如果要写入磁盘,那么磁盘io性能消耗也比

黑马程序员——Java基础——IO流(三)—对象的序列化(持久化),管道流,操作基本数据类型的流对象

第一讲 对象序列化(持久化) 概述: 将堆内存中的对象存入硬盘,以包括对象的数据,称为持久化或序列化 使用的类:ObjectInputStream和ObjectOutputStream 特有方法: ObjectInputStream Object readObject():读取 ObjectOutputStream void writeObject(obj):写入 1 /* 2 * 需求:将一个对象序列化,并从硬盘中读取序列化的对象 3 * 4 */ 5 import java.io.*; 6

python对象序列化或持久化的方法

http://blog.csdn.net/chen_lovelotus/article/details/7233293 一.Python对象持久化方法 目前为止,据我所知,在python中对象持久化有以下几种方法: 1. 使用(dbhash/bsddb, dbm, gdbm, dumbdbm 等)以及它们的"管理器"( anydbm ).只提供了 Python 字 符串的永久性储存. 提供一个类似字典和文件的对象,可以完成字符串的永久性存储. 2. 使用marshal和pickle来序

Unity 序列化

Script Serialization http://docs.unity3d.com/Manual/script-Serialization.html 自定义序列化及例子: http://docs.unity3d.com/ScriptReference/ISerializationCallbackReceiver.OnBeforeSerialize.html 以下是上面2篇的摘要: 脚本的字段需要满足什么条件才能被序列化?(必须同时满足) 1. public 类型,或者有 [Serializ