Unity Scene 数据迁移研究
来源:互联网 发布:网络陷阱有哪些 编辑:程序博客网 时间:2024/06/04 01:16
背景
项目(手游)进行到中后期,在进行代码重构过程中,难免会遇到一些与数据相关的问题。
例如我今天遇到的一个:Unity Scene 中存在了一些关卡数据,这些关卡数据是由关卡设计者放在场景中的物体上配置的(Monobehavior),借由场景进行数据的保存。
当然,如果关卡设计不是使用 unity scene 作为媒介来保存,可能就不存在这个问题了。
言归正传,重构(Refactor)过程中,我需要将 Monobehavior 组件中散乱存储的数据项,集中到一个数据结构中,做一个聚合,让代码结构更加优化。此重构的优化目标此处不做讨论。
假设原先有 十几个场景,每个场景有十几个保存数据的 Monobehavior,如何将原来的数据迁移到新的结构中呢?
Unity 中对于重构的支持
Unity 通过 Monobehavior 中的 SerializeFiled 属性标记需要序列化存储的成员。然而成员变量名字的修改,会导致序列化数据的丢失。原因是识别序列化数据和对应成员是使用成员的名字来进行的,改名会导致 Unity 认为你删除了一个旧的成员,而添加了一个新的成员。
简单重命名可以使用 以下方法来避免数据丢失:
_playerPrefab 修改为 _newPlayerPrefab
//改名之前[SerializeField]private GameObject _playerPrefab;//改名之后[SerializeField][UnityEngine.Serialization.FormerlySerializedAs("_playerPrefab")]private GameObject _newPlayerPrefab;
然而对于这样的修改:
[SerializeField]private float _a;[SerializeField]private float _b;
_a 和 _b 字段聚集到一个类 AB 中
[System.Serializable]public class AB{ public float A; public float B;}
最后需要这样的存储方式:
[SerializeField]private AB _ab;
暂时还未找到方便的 Unity 内置提供解决方案。
各位看官如果知道,可以指出来~(虚心求教)
解决思路
- 遍历所有场景
- 遍历所有目标脚本
- 将存储在原来位置的数据放到目标结构中
- 存储修改后数据
过程
思路很清楚了,不过过程是艰辛的。(似乎是似曾相识是吗?)
遍历所有场景
public static string[] FindAllScene(string scenePath) { return System.IO.Directory.GetFiles(scenePath, "*.unity"); }
遍历所有目标脚本
public static T[] FindAllComponent<T>() where T : Object { return Resources.FindObjectsOfTypeAll<T>(); }
将存储在原来位置的数据放入目标结构中
public static void MoveData(MonoBehaviour ab) { SerializedObject serializedObject = new SerializedObject(ab); serializedObject.FindProperty("_ab.A").floatValue = serializedObject.FindProperty("_a").floatValue; serializedObject.FindProperty("_ab.B").floatValue = serializedObject.FindProperty("_b").floatValue; }
存储修改后数据
这个部分包含了两个部分,一个是在数据移动的方法中添加一个调用:
serializedObject.ApplyModifiedProperties();
添加后:
public static void MoveData(MonoBehaviour ab) { SerializedObject serializedObject = new SerializedObject(ab); serializedObject.FindProperty("_ab.A").floatValue = serializedObject.FindProperty("_a").floatValue; serializedObject.FindProperty("_ab.B").floatValue = serializedObject.FindProperty("_b").floatValue; serializedObject.ApplyModifiedProperties(); }
另一部分则是场景的保存:
EditorSceneManager.SaveScene(scene);
最后给出最终的完成代码:
public static void Move() { EditorSceneManager.SaveOpenScenes(); string[] paths = System.IO.Directory.GetFiles("Assets/Maps", "*.unity"); for (int i = 0; i < paths.Length; i++) { Scene scene = EditorSceneManager.OpenScene(paths[i]); BoostArea[] scripts = Resources.FindObjectsOfTypeAll<BoostArea>(); for (int j = 0; j < scripts.Length; j++) { MoveData(scripts[j]); } EditorSceneManager.SaveScene(scene); } }
注意几点:
- 使用 EditorUtility.SetDirty() 是不能正确标记场景被修改过的。具体看文档
- 使用 serializedObject.ApplyModifiedProperties(); 会使得脚本所属的 prefab 也会被修改保存
- 经过测试 EditorSceneManager.MarkSceneDirty 也不能完成这个多场景遍历同时保存修改的操作。(没有使用 serializedObject.ApplyModifiedProperties(),而是直接使用脚本的实例相互赋值)
- Unity Scene 数据迁移研究
- 关于MongDB数据迁移方案的研究
- Unity Scene场景自定义坐标轴
- DB2数据库重建及表数据迁移探讨研究
- Extremely slow scene loading with Unity Android
- Unity在Scene下绘制图片
- 在unity的scene中画五角星
- unity OnDrawGizmosSelected只在scene起作用
- unity 5 Assetbundle 打包 scene 工具
- Unity在Scene下绘制图片
- unity scene 无缝切换(缓存)
- unity OnDrawGizmosSelected只在scene起作用
- unity Scene.isDirty属性返回问题
- 虚拟机迁移研究
- 虚拟机迁移研究
- scene
- Scene
- 数据迁移
- Python如何忽略warning的输出
- 问题3--yum安装的php执行的时候报错
- 计161_Problem W: 武功秘籍
- 关于逻辑运算符的理解
- C++ 基础(六) —— 函数(2)
- Unity Scene 数据迁移研究
- 2017-03-24
- 问题4--centos怎么设置时间与另一台服务器时间同步
- CF 787A
- js中的事件委托技术
- JAVA内部类的一些总结
- 线段树操作中的一些预判方法【UOJ 228】【codeforces 438D】
- 问题5--zabbix数据库连接问题
- 浅谈Java中的对象和对象引用