据我所知unity Serialization对于基本数据类型很是好用,但处理复类型时就有些基础缺陷了。
个人需求是链接组件和文件并永久保存这种关系。而组件(或游戏对象)的InstanceID无论用,由于每次场景加载都会不同。
Unity内置的持久化策略是经过“m_LocalIdentfierInFile”(将检视面板视图切换为Debug模式便可看到该字段)来链接场景文件和游戏对象及其组件的(这个确定是Unity的拼写错误,应该是Identifier,固然它也没有要改正的倾向)。
因此我也能够利用这个字段来作些什么啊。但最大的难题是UnityEngine没有提供任何可使用该字段的接口,也没说明要如何用,几番查证得知这是在引擎的C++端实现的。
废话少说,多方尝试以后最后想出了一个简单的解决办法,就是在编辑器中复制一份“m_LocalIdentfierInFile”,并将其保存为序列化的属性。
可是,它对于运行时建立的游戏对象或组件并无论用。
下面是实现方法
:
- // This is a copy of the "m_localIndentiferInFile"
- // (don't forget to use [Serializable] on the class)
- [SerializeField]
- private int persistentID = -1;
复制代码
结合下面这段代码就能够访问“m_LocalIdentfierInFile”了,确保该段代码添加了编辑器预约义宏(#ifdef UNITY_EDITOR),而且不要引用UnityEditor命名空间,不然会致使编译失败。
- // Init this instance, it's public so it can be called from a InspectorScript
- // is only set via the unity editor
- public void init ()
- {
- #if UNITY_EDITOR
- PropertyInfo inspectorModeInfo =
- typeof(UnityEditor.SerializedObject).GetProperty ("inspectorMode",
- BindingFlags.NonPublic | BindingFlags.Instance);
- UnityEditor.SerializedObject serializedObject =
- new UnityEditor.SerializedObject (comp);
- inspectorModeInfo.SetValue (serializedObject, UnityEditor.InspectorMode.Debug, null);
- UnityEditor.SerializedProperty localIdProp =
- serializedObject.FindProperty ("m_LocalIdentfierInFile")
- //Debug.Log ("found property: " + localIdProp.intValue);
- persistentID = localIdProp.intValue;
- //Important set the component to dirty so it won't be overriden from a prefab!
- UnityEditor.EditorUtility.SetDirty (this);
- #endif
- }
复制代码
上面的脚本最初由thelackey3326发布在Unity论坛中,最后加上一句“UnityEditor.EditorUtility.SetDirty (this);”,以防预制件persistentID被重写。
下面是在OnEnable()中调用init()方法:
- public void OnEnable ()
- {
- myPersist.init ();
- }
复制代码
这只在场景保存后有用(保存以前m_LocalIdentfierInFile == 0),在建立了游戏对象或拖拽预制件以后保存场景且至少点击一次游戏对象!
一般若是将预制件拖拽到场景中,就表示点击了它并进行了一些操做。
在场景即将保存时能够访问其中一些数据,Unity没有提供保存场景后进行访问的方法。下面的代码是在保存场景前调用init()函数:
- static string[] OnWillSaveAssets (string[] paths)
- {
- Object[] objs = Component.FindObjectsOfType (typeof(PersistObject));
- //Debug.Log ("OnWillSaveAssets " + objs.Length);
- foreach (Object obj in objs) {
- PersistObject persist = (PersistObject)obj;
- persist.init ();
- }
- return paths;
- }
复制代码
以上代码表示,若是建立一个游戏对象,并使用编辑器获取“m_LocalIdentfierInFile”字段,就必须在此以后至少保存两次场景。第一次是让Unity设置“m_LocalIdentfierInFile”,第二次是将其保存到局部变量中。这并不是最便捷的方法,但也够用了,只需使用持久化的游戏对象设置下场景就好。