Unity的序列化问题配表问题用什么方法比较好

关于序列化Serializable
关于序列化Serializable
常常看说序列化,说什么发消息要序列化,存数据也需要序列化。今天就看了看这个到底是什么东西。是什么序列化是将对象状态转换为可保持或传输的格式的过程。与序列化相对的是反序列化,它将流转换为对象。这两个过程结合起来,可以轻松地存储和传输数据。简单的说就是把对象转换成字节然后到内存中,数据库中或者是文件中的一个过程。过程再通俗点讲就是学习武功时候,师傅给徒弟说武功口诀这个过程,然后徒弟把武功口诀一招一式练成就是反序列化。在Unity中过程大概知道序列化是什么东西了,我们来看看他在unity中是怎么样的。不知道你们遇到过这种情况没有,就是在运行unity时,你去更改一些组件的变量,然后停止运行,再去看你所更改的变量又还原到了你运行之前没有更改的那个数值了。其实这个就是unity序列化的特性吧。这个是因为unity其实是两层,C++层与unity控制层,因为unity是用c++编写的,但是我们自己编写的脚本是c#,就会有一个交互。当我们点击运行按钮时,先是把所有的序列化数据在内部创建,然后把他们存在c++这一层;然后清除unity控制层这边所有的内存和消息;然后加载我们编写的脚本;最后再把c++层中存储的序列化数据反序列化到unity控制层中去。所以我们在运行时更改组件上的变量其实是没有用的,因为我仅仅是更改unity控制层上的数据,正真数据是从c++层读取出来的。在Unity中使用在unity系统中用到序列化的有Inspector面板,预制物体,实例化物体,场景存储,加载场景,代码的编译等等,可以看看这个文章讲很清楚他们是怎么在系统中用序列化的。在脚本使用只需要序列化的类名前面加上 [Serializable]即可,加上System命名空间。[Serializable]class Animal{ &
}class MyScript : MonoBehaviour{ & & &public Animal[]
}这个写法可以把类中公共变量做序列化,私有变量需要序列化需要加上[SerializeField],公共变量不想被序列化加上 [NonSerializable]就可以了。当然静态(static),常量(const),只读(readonly)的变量,抽象类这些是不能被序列化的。当然序列化在unity中也又不足,像什么不支持多态什么的,在上面的那个文章上也讲了的,我就不翻译了。差不多就说这么多吧,这些就是我自己对序列化的一些理解吧,有什么说的不对,咱们都可以讨论哦~
本文仅代表作者观点,不代表百度立场。系作者授权百家号发表,未经许可不得转载。
百家号 最近更新:
简介: 一个程序员的成长之路
作者最新文章2015年7月 Web 开发大版内专家分月排行榜第三
2015年7月 Web 开发大版内专家分月排行榜第三
匿名用户不能发表回复!|
每天回帖即可获得10分可用分!小技巧:
你还可以输入10000个字符
(Ctrl+Enter)
请遵守CSDN,不得违反国家法律法规。
转载文章请注明出自“CSDN(www.csdn.net)”。如是商业用途请联系原作者。程序写累了,就来玩玩酷跑小游戏吧,嘿嘿。
雨松MOMO送你一首歌曲,嘿嘿。
Unity3D研究院编辑器之序列化的对象修改格式(十九)
Unity3D研究院编辑器之序列化的对象修改格式(十九)
围观18663次
编辑日期: 字体:
一般在做编辑器的时候会给策划做一些脚本或者ScriptableObject,让策划进行或拽赋值等操作。举个例子假如开始策划说我只需要拖放一个GameObject,但是N天以后策划说这里想拖多个GameObject. 那么如果开始序列化的数据不是List&GameObject&那么就悲剧了,数据结构一变策划之前拖拽过的工作都玩白做了。。有些人为了做兼容不得不在写一个新的数据结构让策划来填写,但是这样就得是多个变量了,代码看起来比较丑了。
其实Unity也意识到这个问题了。他们提供了一个方案
FormerlySerializedAs(name)
public string a1; [FormerlySerializedAs("a1")] public string a2;
这样可以把a1删除了,然后 a1序列化的数据就保存在a2里。但是它这个有局限性,比如这里我想把a1的数据放到一个新的对象里就不行了。比如这样
12345678910111213
public class NewBehaviourScript : MonoBehaviour {& public Hero hero;&}&&[System.Serializable]public class Hero{ [FormerlySerializedAs("a1")] public string a2;}
而且它这个只能替换相同数据结构,假如我想GameObject放到List&GameObject&里也不行了。。。所以我写了一个批量赋值的工具。把MonoBehaviour和ScriptableObject以泛型的形式传进去,让旧的数据等于新的数据、然后在类里把就把旧的变量直接删除掉就好了。
12345678910111213141516171819202122232425262728293031323334353637383940
using UnityEngine;using System.Collections;using UnityEditor;using System.Collections.Generic;&public class TestEditor : Editor {&& [MenuItem("1/ModifyPrefab")] static void Test() {
ModifyAsset.ModifyPrefab&NewBehaviourScript&(delegate(Component obj) {
NewBehaviourScript&&script = obj as NewBehaviourScript;
script.hero.objects = new List&GameObject&(){script.obj};
}); }&&& [MenuItem("1/ModifyScene")] static void Test1() {
ModifyAsset.ModifyScene&NewBehaviourScript&(delegate(Component obj){
NewBehaviourScript&&script = obj as NewBehaviourScript;
script.hero.objects = new List&GameObject&(){script.obj};
}); }& [MenuItem("1/ModifyScriptableObject")] static void Test2() {
ModifyAsset.ModifyScriptableObject&MyAsset&(delegate(ScriptableObject obj) {
MyAsset&&script = obj as MyAsset;
script.hero.objects = new List&GameObject&(){script.obj}; &
可能出现这个问题的只有三处
1.prefab里的数据
2.scene里的数据
3.ScriptableObject
核心代码就是遍历、找到以后回调出去。
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
#if UNITY_EDITORusing UnityEngine;using System.Collections;using System.Collections.Generic;using UnityEditor;using UnityEngine.SceneManagement;using System.Reflection;using System;using UnityEditor.SceneManagement;public class ModifyAsset{ static public void ModifyPrefab&T& (Action&Component&callBack) where T: MonoBehaviour {
string[] guids = AssetDatabase.FindAssets ("t:Prefab");&
foreach (string guid in guids) {
string path = AssetDatabase.GUIDToAssetPath (guid);
GameObject obj = AssetDatabase.LoadAssetAtPath&GameObject& (path);
T[] scripts = obj.GetComponentsInChildren&T& (true);&
for (int i = 0; i & scripts.Length; i++)
callBack (scripts[i]);
EditorUtility.SetDirty (obj);
AssetDatabase.SaveAssets ();
AssetDatabase.Refresh ();
} }& static public void ModifyScene&T& (Action&Component&callBack) where T: MonoBehaviour {
EditorSceneManager.SaveOpenScenes ();
foreach (EditorBuildSettingsScene editorBuildSettingsScene in EditorBuildSettings.scenes)
Scene scene=EditorSceneManager.OpenScene (editorBuildSettingsScene.path);
T[] scripts =
Resources.FindObjectsOfTypeAll&T& ();
for (int i = 0; i & scripts.Length; i++)
callBack (scripts[i]);
EditorSceneManager.SaveScene(scene);
AssetDatabase.SaveAssets ();
AssetDatabase.Refresh ();
} }& static public void ModifyScriptableObject&T& (Action&ScriptableObject&callBack) where T: ScriptableObject {
string[] guids = AssetDatabase.FindAssets ("t:ScriptableObject");
foreach (string guid in guids) {
string path = AssetDatabase.GUIDToAssetPath (guid);
if (path.EndsWith (".asset")) {
T script = AssetDatabase.LoadAssetAtPath&T& (path);
if (script != null) {
callBack (script);
EditorUtility.SetDirty (script);
AssetDatabase.SaveAssets ();
AssetDatabase.Refresh ();
} }&}#endif
序列化对象 ,把obj放到hero.objects[0]里面,然后在把obj删除就行了
123456789101112131415161718
using UnityEngine;using System.Collections;using UnityEngine.Serialization;using System.Collections.Generic;using UnityEngine.SceneManagement;&public class NewBehaviourScript : MonoBehaviour { public GameObject obj; public Hero hero;}&&[System.Serializable]public class Hero{ public List&GameObject& objects;}
ScriptableObject
12345678910111213
using UnityEngine;using System.Collections;using System.Collections.Generic;&[CreateAssetMenu]public class MyAsset : ScriptableObject {&& public GameObject obj; public Hero hero;&&}
OK这样数据就拷贝过去了。然后就可以把旧的数据结构删除了。
做到这里其实还没有完,因为这里就算在脚本里删除了变量名, 那这个变量名之前序列化的数据还在prefab里序列化这。除非修改保存一下才行,所以最好在批量执行一下
EditorUtility.SetDirty (obj);
另外,如果大家有更好的方法处理这个,欢迎再下面留言给我!
Unity版本 5.3.1
本文固定链接:
转载请注明:
雨松MOMO提醒您:亲,如果您觉得本文不错,快快将这篇文章分享出去吧 。另外请点击网站顶部彩色广告或者捐赠支持本站发展,谢谢!
作者:雨松MOMO
专注移动互联网,Unity3D游戏开发
如果您愿意花10块钱请我喝一杯咖啡的话,请用手机扫描二维码即可通过支付宝直接向我捐款哦。
您可能还会对这些文章感兴趣!209被浏览7448分享邀请回答coding.net/u/NxShow/p/NxLibrary/git05 条评论分享收藏感谢收起

我要回帖

更多关于 序列化问题 的文章

 

随机推荐