Unity序列化和持久化

据我所知unity Serialization对于基本数据类型非常好用,但处理复类型时就有些基础缺陷了。
 
我的需求是连接组件和文件并永久保存这种关系。而组件(或游戏对象)的InstanceID不管用,因为每次场景加载都会不一样。
Unity序列化和持久化
 
Unity内置的持久化策略是通过“m_LocalIdentfierInFile”(将检视面板视图切换为Debug模式即可看到该字段)来连接场景文件和游戏对象及其组件的(这个肯定是Unity的拼写错误,应该是Identifier,当然它也没有要改正的倾向)。
 
所以我也可以利用这个字段来做些什么啊。但最大的难题是UnityEngine没有提供任何可以使用该字段的接口,也没说明要如何用,几番查证得知这是在引擎的C++端实现的。
 
废话少说,多方尝试之后最后想出了一个简单的解决办法,就是在编辑器中复制一份“m_LocalIdentfierInFile”,并将其保存为序列化的属性。
 
但是,它对于运行时创建的游戏对象或组件并不管用。
 
下面是实现方法 Unity序列化和持久化 :
 
  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序列化和持久化 
 
在场景即将保存时可以访问其中一些数据,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”,第二次是将其保存到局部变量中。这并非最便捷的方法,但也够用了,只需使用持久化的游戏对象设置下场景就好。
Unity序列化和持久化 

原文链接: https://www.cnblogs.com/clschen/p/5426612.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

    Unity序列化和持久化

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/232451

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月13日 下午3:29
下一篇 2023年2月13日 下午3:29

相关推荐