精华内容
参与话题
问答
  • unity序列化

    2019-09-20 21:27:24
    unity序列化unity的开发中起着举重足轻的地位,许多核心的功能都是基于序列化和反序列化来实现的。序列化简单来讲就是就是将我们所要保存的数据进行二进制存储,然后当我们需要的时候,在读取二进制文件,反序列...

    什么是序列化

    • unity的序列化在unity的开发中起着举重足轻的地位,许多核心的功能都是基于序列化和反序列化来实现的。序列化简单来讲就是就是将我们所要保存的数据进行二进制存储,然后当我们需要的时候,在读取二进制文件,反序列化回来。下面是一些常用的序列化的例子:

      • 存储脚本化的数据。在我们的c#代码中,可以将我们所要存储的数据进行序列化,进行存储
      • prefab与初始化。在unity开发过程中我们会制作很多的预制体(prefab),这些prefab都是序列化,以二进制的形式保存的。当你要对预制体进行初始化的时候,unity根据之前序列化的信息新建出一个物体,然后将物体上的信息反序列化回去,实现类似于clone的效果。
      • 在unity编辑器的拓展功能,AssetBundle等等,都可以看到序列化的身影。
    • 可序列化对象

      • 公有的,或者有[SerializeField]属性,非静态,非常量,非只读
      • 自定义非抽象类,并且有Serializable属性
      • 继承自unity.object的类
      • 数组和List
      注意:
      • 字典不能通过添加Serializable属性进行序列化
      • 如果一个类基类不能被序列化,那它即便添加了序列化特性也无法被序列化
      • 序列化不能保存另一个要反序列化的对象指针,因为反序列化是new一个新的对象,指针指向的内存将不会是原对象
    • 可采用unity编辑器的序列化类ScriptableObject,当我们继承这个基类,我们就可以调用unity给我们的接口进行序列化了。具体的序列化接口可以到unity的官方接口文档上查看使用方法,这里不具体介绍。

    • 下面来讲讲具体开发过程中个人遇到的坑

      • 首先给出一段开发过程中的报错信息
      Serialization depth limit 7 exceeded at 'XNodeScripts::ConfigNode.nodeList'. There may be an object composition cycle in one or more of your serialized classes.
      
      Serialization hierarchy:
      8: XNodeScripts::ConfigNode.nodeList
      7: XNodeScripts::ConfigNode.nodeList
      6: XNodeScripts::ConfigNode.nodeList
      5: XNodeScripts::ConfigNode.nodeList
      4: XNodeScripts::ConfigNode.nodeList
      3: XNodeScripts::ConfigNode.nodeList
      2: XNodeScripts::ConfigNode.nodeList
      1: XNodeScripts::ConfigNode.nodeList
      0: XNodeScripts::SelectMsgNode.rootNode

      这里的报错信息提示我们我在创建序列化数据nodeList的时候,可能是在这个nodeList里面有循环的序列化。这边我们发现unity还提示我们序列化的深度为7。我在网上查到,原来我们的子系统是构建在序列化系统之上的,所以如果放任其死循环的序列化的话,当一个非常大的序列化流将导致整个系统崩溃。为了避免这样的情况,unity采用了一个深度为7的阙值,及循环序列化为空的子集最多只能为7个。我们在进行序列化的创建的时候,一个非常常见的错误就是通过序列化构造一个类似树状结构的数据结构,在我们声明的序列化类里面,如果还有包含本身的对象,类似于

      [Serializable]
      public class DepthClass : ScriptableObject
      {
          public List<DepthClass> depthObjects; 
      }

      上诉的这种序列化结构,就会产生我之前所示的系统报错。有效的避免空值的序列化,对于树状结构包括字典的存储,我采用的是List key的存储方式,对下一个子节点,都用字符串作为一个key值来存储,然后将所有的节点都存储在一个List中。这样我们通过key来寻找节点,其中我们可以采用堆存储或者更加高效的查询方式,来避免效率的底下。目前还没有想到更好的解决方法。。。23333

    885799-20190412141716151-1366583319.png

    转载于:https://www.cnblogs.com/fzuljz/p/11168131.html

    展开全文
  • Unity序列化

    千次阅读 2017-12-19 19:57:50
    ScriptableObject类型经常用于存储一些unity3d本身不可以打包的一些object,比如字符串,一些类对象等。 [System.Serializable] public class SkillItem { public int skillid; public string skillname; } ...

    ScriptableObject

    参考网址

    ScriptableObject类型经常用于存储一些unity3d本身不可以打包的一些object,比如字符串,一些类对象等。

    [System.Serializable]
    public class SkillItem
    {
        public int skillid;
        public string skillname;
    }
    
    [System.Serializable]
    public class GameDataScriptable :ScriptableObject
    {
        public List<SkillItem> skillItemList = new List<SkillItem>();
    }

    打包ScriptObject,ScriptObject 可以存储任何数据类型

    //通过ScriptableObject创建一个对象的实例  
    GameDataScriptable gs = ScriptableObject.CreateInstance<GameDataScriptable>();  
    //对对象的属性进行赋值  
    for(int i=1;i<3;i++){  
        SkillItem item = new SkillItem();  
        item.SkillId = i;                 
        item.SkillName = "技能" + i;    
        gs.SkillDictionary.Add(item);  
    }
     //创建资源文件(可以在编辑器下直接编辑数据)  
    AssetDatabase.CreateAsset(gs, "Assets/GameDataConfig.asset");  
    //将资源反序列化为一个对象  
    Object o = AssetDatabase.LoadAssetAtPath("Assets/GameDataConfig.asset", typeof(GameDataScriptable));  
    //assetbundle文件只能在运行时加载,并且只能通过WWW加载  
    BuildPipeline.BuildAssetBundle(o, null, "Assets/GameData.assetbundle");  
    //删除临时的资源文件  
    AssetDatabase.DeleteAsset("Assets/GameDataConfig.asset");  

    运行时加载这个数据资源

    public class LoadFile:MonoBehaviour  
    {  
        IEnumerator Start ()  
        {  
          WWW www = new WWW("file://" + Application.dataPath + "/../GameDataConfig.assetbundle");  
          yield return www;  
          //转换资源为Test,这个test对象将拥有原来在编辑器中设置的数据。  
          GameDataScriptable test = www.assetBundle.mainAsset as GameDataScriptable;  
        }  
    }  

    提示:这其实就是把对象的实例打包,如果ScriptObject 属性中包括其他类的实例,则这些类需要加上[Serializable]序列化。通过这种方法,可以将系统需要的数据打包,
    加载后直接转换为预定义的类型,可大大加快数据加载读取的速度,具有更高的效率。

    SerializeField

    强制Unity序列化私有变量
    当Unity序列化脚本时,只会序列化公有成员,如果你也想序列化私有成员,可以添加上[SerializeField]属性

    以下可被序列化:

    • 不是静态的公有成员
    • 不是静态,不是公有,被标记为[SerializeField]属性
    • 不能序列化 static 成员
    • 不能序列化 属性(properties)

    Serializable

    序列化类型:

    • 所有继承自UnityEngine.Object 的类,例如:GamObject,Component,MonoBehaviour,Texture2D,AnimationClip
    • 所有基础类型,例如 int,string,float,bool
    • 一些内置的类型,例如 Vactor2,Vector3,Vector4,Quaternion,Matrix4x4,Color,Rect,LayerMask
    • 可序列化类型的数组
    • 可序列化类型的List
    • Enums
    • Structs

    注意:
    1、不要将一个成员添加到数组或者list两次,当数组或者list被序列化的时候,你将得到这个成员两次,而在新的list或者数组再拷贝一份
    2、Unity不会序列化字典,但是你可以将key,和value分别存储在list中

    [System.Serializable]  
    public class SerializableDictionary<TKey, TValue> : Dictionary<TKey, TValue>, ISerializationCallbackReceiver  
    {  
        [SerializeField]  
        private List<TKey> _keys = new List<TKey>();  
        [SerializeField]  
        private List<TValue> _values = new List<TValue>();  
    
        public void OnBeforeSerialize()  
        {  
            _keys.Clear();  
            _values.Clear();  
            _keys.Capacity = this.Count;  
            _values.Capacity = this.Count;  
            foreach (var kvp in this)  
            {  
                _keys.Add(kvp.Key);  
                _values.Add(kvp.Value);  
            }  
        }  
    
        public void OnAfterDeserialize()  
        {  
            this.Clear();  
            int count = Mathf.Min(_keys.Count, _values.Count);  
            for (int i = 0; i < count; ++i)  
            {  
                this.Add(_keys[i], _values[i]);  
            }  
        }  
    }  
    
    //usage:
    //[System.Serializable]  
    //public class MyDictionary:SerializableDictionary<int,GameObject>{};
    //public MyDictionary dic;

    ISerializationCallbackReceiver是Unity提供的,可以在序列化/反序列化过程中监听回调的一个接口,需要实现OnBeforeSerializeOnAfterDeserialize两个方法

    今天看到UWA更加详细的一篇,可作参考
    Unity插件开发基础—浅谈序列化系统

    展开全文
  • Unity 序列化

    2018-02-05 20:56:39
    1.Unity 支持的类型都可以被序列化,也就是可以在编辑界面看到。 例如 List ,public int ,public float , public Vector3 ,等等。 或者有注明 类 如下 [Serializable] class Trouble { public Trouble ...

    1.Unity 支持的类型都可以被序列化,也就是可以在编辑界面看到。
    例如 List ,public int ,public float , public Vector3 ,等等。 或者有注明 类
    如下
    [Serializable]
    class Trouble
    {
    public Trouble t1;
    public Trouble t2;
    public Trouble t3;
    }等等
    但是例如 Queue ,字典,栈 就不被支持,所以在脚本中定义 ,要用 new 来创建。
    具体可以类型,序列化可以参考
    https://docs.unity3d.com/Manual/script-Serialization.html

    展开全文
  • unity序列化So you are writing a really cool editor extension in Unity and things seem to be going really well. You get your data structures all sorted out are really happy with how the tool you have w...

    unity序列化

    So you are writing a really cool editor extension in Unity and things seem to be going really well. You get your data structures all sorted out are really happy with how the tool you have written works.

    因此,您在Unity中编写了一个非常酷的编辑器扩展,一切似乎进行得很顺利。 您可以整理好所有的数据结构,这对您编写的工具的工作方式非常满意。

    Then you enter and exit play mode.

    然后进入和退出播放模式。

    Suddenly all the data you had entered is gone and your tool is reset to the default, just initialized state. It’s very frustrating! “Why does this happen?” you ask yourself. The reason has to do with how the managed (mono) layer of Unity works. Once you understand it, then things get much easier :)

    突然,您输入的所有数据都消失了,您的工具被重置为默认的初始化状态。 非常令人沮丧! “为什么会这样?” 你问自己。 原因与Unity的托管(单)层的工作方式有关。 一旦了解了,事情就会变得容易得多:)

    What happens when an assembly is reloaded? When you enter / exit play mode or change a script Unity has to reload the mono assemblies, that is the dll’s associated with Unity.

    重新加载装配时会发生什么? 当您进入/退出播放模式或更改脚本时,Unity必须重新加载单声道程序集,即与Unity关联的dll。

    On the user side this is a 3 step process:

    在用户方面,这是一个三步过程:

      What this means is that for your data structures / information to survive an assembly reload you need to ensure that it can get serialized into and out of c++ memory properly. Doing this also means that (with some minor modifications) you can save this data structure to an asset file and reload it at a later date.

      这意味着要使您的数据结构/信息能够在程序集重新加载后继续存在,您需要确保可以正确地将其序列化到c ++内存中以及从中取出。 这样做还意味着(稍作修改)您可以将该数据结构保存到资产文件中,并在以后重新加载。

      How do I work with Unity’s serialization? The easiest way to learn about Unity serialization is by working through an example. We are going to start with a simple editor window, it contains a reference to a class which we want to make survive an assembly reload.

      如何使用Unity的序列化? 学习Unity序列化的最简单方法是通过一个示例。 我们将从一个简单的编辑器窗口开始,它包含对一个类的引用,该类要在程序集重新加载后继续存在。

      1

      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      using UnityEngine;
      using UnityEditor;
      public class MyWindow : EditorWindow
      {
      private SerializeMe m_SerialziedThing;
      [MenuItem ("Window/Serialization")]
      static void Init () {
      GetWindow ();
      }
      void OnEnable ()
      {
      hideFlags = HideFlags.HideAndDontSave;
      if (m_SerialziedThing == null)
      m_SerialziedThing = new SerializeMe ();
      }
      void OnGUI () {
      GUILayout.Label ("Serialized Things", EditorStyles.boldLabel);
      m_SerialziedThing.OnGUI ();
      }
      }

      1

      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      using UnityEngine ;
      using UnityEditor ;
      public class MyWindow : EditorWindow
      {
      private SerializeMe m_SerialziedThing ;
      [ MenuItem ( "Window/Serialization" ) ]
      static void Init ( ) {
      GetWindow ( ) ;
      }
      void OnEnable ( )
      {
      hideFlags = HideFlags . HideAndDontSave ;
      if ( m_SerialziedThing == null )
      m_SerialziedThing = new SerializeMe ( ) ;
      }
      void OnGUI ( ) {
      GUILayout . Label ( "Serialized Things" , EditorStyles . boldLabel ) ;
      m_SerialziedThing . OnGUI ( ) ;
      }
      }

      1

      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      using UnityEditor;
      public struct NestedStruct
      {
      private float m_StructFloat;
      public void OnGUI ()
      {
      m_StructFloat = EditorGUILayout.FloatField("Struct Float", m_StructFloat);
      }
      }
      public class SerializeMe
      {
      private string m_Name;
      private int m_Value;
      private NestedStruct m_Struct;
      public SerializeMe ()
      {
      m_Struct = new NestedStruct();
      m_Name = "";
      }
      public void OnGUI ()
      {
      m_Name = EditorGUILayout.TextField( "Name", m_Name);
      m_Value = EditorGUILayout.IntSlider ("Value", m_Value, 0, 10);
      m_Struct.OnGUI ();
      }
      }

      1

      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      using UnityEditor ;
      public struct NestedStruct
      {
      private float m_StructFloat ;
      public void OnGUI ( )
      {
      m_StructFloat = EditorGUILayout . FloatField ( "Struct Float" , m_StructFloat ) ;
      }
      }
      public class SerializeMe
      {
      private string m_Name ;
      private int m_Value ;
      private NestedStruct m_Struct ;
      public SerializeMe ( )
      {
      m_Struct = new NestedStruct ( ) ;
      m_Name = "" ;
      }
      public void OnGUI ( )
      {
      m_Name = EditorGUILayout . TextField ( "Name" , m_Name ) ;
      m_Value = EditorGUILayout . IntSlider ( "Value" , m_Value , 0 , 10 ) ;
      m_Struct . OnGUI ( ) ;
      }
      }

      When you run this and force an assembly reload you will notice that any value in the window you have changed will not survive. This is because when the assembly is reloaded the reference to the ‘m_SerialziedThing’ is gone. It is not marked up to be serialized.

      当您运行此命令并强制重新加载装配件时,您会注意到更改的窗口中的任何值都将无法保存。 这是因为重新加载程序集时,对'm_SerialziedThing'的引用已消失。 它没有标记为要序列化。

      There are a few things that need to be done to make this serialization work properly: In MyWindow.cs:

      要使此序列化正常工作,需要做一些事情:在MyWindow.cs中:

        In SerializeMe.cs:

        在SerializeMe.cs中:

          After adding these flags open the window and modify the fields. You will notice that after an assembly reload that the fields retain their values; that is apart from the field that came from the struct. This brings up the first important point, structs are not very well supported for serialization. Changing ‘NestedStruct’ from a struct to a class fixes this issue.

          添加这些标志后,打开窗口并修改字段。 您会注意到,在装配件重装后,这些字段将保留其值。 这与来自该结构的字段不同。 这引出了第一个重要的观点,结构没有很好地支持序列化。 将“ NestedStruct”从结构更改为类可解决此问题。

          The code now looks like this:

          现在的代码如下所示:

          1

          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          12
          13
          14
          15
          16
          17
          18
          19
          20
          21
          22
          23
          24
          25
          26
          27
          28
          29
          30
          31
          32
          33
          34
          35
          36
          37
          38
          39
          40
          41
          42
          43
          44
          45
          46
          47
          48
          49
          50
          51
          52
          53
          54
          55
          56
          57
          58
          59
          60
          61
          62
          63
          64
          using UnityEngine;
          using UnityEditor;
          public class MyWindow : EditorWindow
          {
          private SerializeMe m_SerialziedThing;
          [MenuItem ("Window/Serialization")]
          static void Init () {
          GetWindow ();
          }
          void OnEnable ()
          {
          hideFlags = HideFlags.HideAndDontSave;
          if (m_SerialziedThing == null)
          m_SerialziedThing = new SerializeMe ();
          }
          void OnGUI () {
          GUILayout.Label ("Serialized Things", EditorStyles.boldLabel);
          m_SerialziedThing.OnGUI ();
          }
          }
          using System;
          using UnityEditor;
          using UnityEngine;
          [Serializable]
          public class NestedStruct
          {
          [SerializeField]
          private float m_StructFloat;
          public void OnGUI ()
          {
          m_StructFloat = EditorGUILayout.FloatField("Struct Float", m_StructFloat);
          }
          }
          [Serializable]
          public class SerializeMe
          {
          [SerializeField]
          private string m_Name;
          [SerializeField]
          private int m_Value;
          [SerializeField]
          private NestedStruct m_Struct;
          public SerializeMe ()
          {
          m_Struct = new NestedStruct();
          m_Name = "";
          }
          public void OnGUI ()
          {
          m_Name = EditorGUILayout.TextField( "Name", m_Name);
          m_Value = EditorGUILayout.IntSlider ("Value", m_Value, 0, 10);
          m_Struct.OnGUI ();
          }
          }

          1

          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          12
          13
          14
          15
          16
          17
          18
          19
          20
          21
          22
          23
          24
          25
          26
          27
          28
          29
          30
          31
          32
          33
          34
          35
          36
          37
          38
          39
          40
          41
          42
          43
          44
          45
          46
          47
          48
          49
          50
          51
          52
          53
          54
          55
          56
          57
          58
          59
          60
          61
          62
          63
          64
          using UnityEngine ;
          using UnityEditor ;
          public class MyWindow : EditorWindow
          {
          private SerializeMe m_SerialziedThing ;
          [ MenuItem ( "Window/Serialization" ) ]
          static void Init ( ) {
          GetWindow ( ) ;
          }
          void OnEnable ( )
          {
          hideFlags = HideFlags . HideAndDontSave ;
          if ( m_SerialziedThing == null )
          m_SerialziedThing = new SerializeMe ( ) ;
          }
          void OnGUI ( ) {
          GUILayout . Label ( "Serialized Things" , EditorStyles . boldLabel ) ;
          m_SerialziedThing . OnGUI ( ) ;
          }
          }
          using System ;
          using UnityEditor ;
          using UnityEngine ;
          [ Serializable ]
          public class NestedStruct
          {
          [ SerializeField ]
          private float m_StructFloat ;
          public void OnGUI ( )
          {
          m_StructFloat = EditorGUILayout . FloatField ( "Struct Float" , m_StructFloat ) ;
          }
          }
          [ Serializable ]
          public class SerializeMe
          {
          [ SerializeField ]
          private string m_Name ;
          [ SerializeField ]
          private int m_Value ;
          [ SerializeField ]
          private NestedStruct m_Struct ;
          public SerializeMe ( )
          {
          m_Struct = new NestedStruct ( ) ;
          m_Name = "" ;
          }
          public void OnGUI ( )
          {
          m_Name = EditorGUILayout . TextField ( "Name" , m_Name ) ;
          m_Value = EditorGUILayout . IntSlider ( "Value" , m_Value , 0 , 10 ) ;
          m_Struct . OnGUI ( ) ;
          }
          }

          Some Serialization Rules

          一些序列化规则

            Scriptable Objects So far we have looked at using normal classes when it comes to serialization. Unfortunately using plain classes has some issues when it comes to serialization in Unity. Lets take a look at an example.

            可编写脚本的对象到目前为止,在序列化方面,我们已经研究了使用普通类。 不幸的是,在Unity中进行序列化时,使用普通类会有一些问题。 让我们看一个例子。

            1

            2
            3
            4
            5
            6
            7
            8
            9
            10
            11
            12
            13
            14
            15
            16
            17
            18
            19
            20
            21
            22
            23
            24
            25
            26
            27
            28
            29
            30
            31
            32
            33
            34
            35
            using System;
            using UnityEditor;
            using UnityEngine;
            [Serializable]
            public class NestedClass
            {
            [SerializeField]
            private float m_StructFloat;
            public void OnGUI()
            {
            m_StructFloat = EditorGUILayout.FloatField("Float", m_StructFloat);
            }
            }
            [Serializable]
            public class SerializeMe
            {
            [SerializeField]
            private NestedClass m_Class1;
            [SerializeField]
            private NestedClass m_Class2;
            public void OnGUI ()
            {
            if (m_Class1 == null)
            m_Class1 = new NestedClass ();
            if (m_Class2 == null)
            m_Class2 = m_Class1;
            m_Class1.OnGUI();
            m_Class2.OnGUI();
            }
            }

            1

            2
            3
            4
            5
            6
            7
            8
            9
            10
            11
            12
            13
            14
            15
            16
            17
            18
            19
            20
            21
            22
            23
            24
            25
            26
            27
            28
            29
            30
            31
            32
            33
            34
            35
            using System ;
            using UnityEditor ;
            using UnityEngine ;
            [ Serializable ]
            public class NestedClass
            {
            [ SerializeField ]
            private float m_StructFloat ;
            public void OnGUI ( )
            {
            m_StructFloat = EditorGUILayout . FloatField ( "Float" , m_StructFloat ) ;
            }
            }
            [ Serializable ]
            public class SerializeMe
            {
            [ SerializeField ]
            private NestedClass m_Class1 ;
            [ SerializeField ]
            private NestedClass m_Class2 ;
            public void OnGUI ( )
            {
            if ( m_Class1 == null )
            m_Class1 = new NestedClass ( ) ;
            if ( m_Class2 == null )
            m_Class2 = m_Class1 ;
            m_Class1 . OnGUI ( ) ;
            m_Class2 . OnGUI ( ) ;
            }
            }

            This is a contrived example to show a very specific corner case of the Unity serialization system that can catch you if you are not careful. You will notice that we have two fields of type NestedClass. The first time the window is drawn it will show both the fields, and as m_Class1 and m_Class2 point to the same reference, modifying one will modify the other.

            这是一个精心设计的示例,展示了Unity序列化系统的一个非常特殊的案例,如果您不小心,可能会抓住您。 您会注意到我们有两个NestedClass类型的字段。 第一次绘制窗口时,它将显示两个字段,并且当m_Class1和m_Class2指向相同的引用时,修改一个将修改另一个。

            Now try reloading the assembly by entering and exiting play mode… The references have been decoupled. This is due to how serialization works when you mark a class as simply [Serializable]

            现在尝试通过进入和退出播放模式重新加载装配件…引用已解耦。 这是由于将类简单标记为[Serializable]时序列化是如何工作的

            When you are serializing standard classes Unity walks through the fields of the class and serializes each one individually, even if the reference is shared between multiple fields. This means that you could have the same object serialized multiple times, and on deserialization the system will not know they are really the same object. If you are designing a complex system this is a frustrating limitation because it means that complex interactions between classes can not be captured properly.

            序列化标准类时,即使引用在多个字段之间共享,Unity也会遍历该类的字段并分别序列化每个字段。 这意味着您可以多次序列化同一对象,并且在反序列化时,系统将不知道它们确实是同一对象。 如果您要设计一个复杂的系统,这将是一个令人沮丧的限制,因为这意味着无法正确捕获类之间的复杂交互。

            Enter ScriptableObjects! ScriptableObjects are a type of class that correctly serializes as references, so that they only get serialized once. This allows complex class interactions to be stored in a way that you would expect. Internally in Unity ScriptableObjects and MonoBehaviours are the same; in userland code you can have a ScriptableObject that is not attached to a GameObject; this is different to how MonoBehaviour works. They are great for general data structure serialization.

            输入ScriptableObjects! ScriptableObjects是一类正确地序列化为引用的类,因此它们仅被序列化一次。 这样可以以您期望的方式存储复杂的类交互。 在Unity内部,ScriptableObjects和MonoBehaviours相同; 在用户区代码中,您可以具有未附加到GameObject的ScriptableObject; 这与MonoBehaviour的工作方式不同。 它们非常适合常规数据结构序列化。

            Let’s modify the example to be able to handle serialization properly:

            让我们修改示例以使其能够正确处理序列化:

            1

            2
            3
            4
            5
            6
            7
            8
            9
            10
            11
            12
            13
            14
            15
            16
            17
            18
            19
            20
            21
            22
            23
            24
            25
            26
            27
            28
            29
            30
            31
            32
            33
            34
            35
            36
            37
            38
            39
            using System;
            using UnityEditor;
            using UnityEngine;
            [Serializable]
            public class NestedClass : ScriptableObject
            {
            [SerializeField]
            private float m_StructFloat;
            public void OnEnable() { hideFlags = HideFlags.HideAndDontSave; }
            public void OnGUI()
            {
            m_StructFloat = EditorGUILayout.FloatField("Float", m_StructFloat);
            }
            }
            [Serializable]
            public class SerializeMe
            {
            [SerializeField]
            private NestedClass m_Class1;
            [SerializeField]
            private NestedClass m_Class2;
            public SerializeMe ()
            {
            m_Class1 = ScriptableObject.CreateInstance ();
            m_Class2 = m_Class1;
            }
            public void OnGUI ()
            {
            m_Class1.OnGUI();
            m_Class2.OnGUI();
            }
            }

            1

            2
            3
            4
            5
            6
            7
            8
            9
            10
            11
            12
            13
            14
            15
            16
            17
            18
            19
            20
            21
            22
            23
            24
            25
            26
            27
            28
            29
            30
            31
            32
            33
            34
            35
            36
            37
            38
            39
            using System ;
            using UnityEditor ;
            using UnityEngine ;
            [ Serializable ]
            public class NestedClass : ScriptableObject
            {
            [ SerializeField ]
            private float m_StructFloat ;
            public void OnEnable ( ) { hideFlags = HideFlags . HideAndDontSave ; }
            public void OnGUI ( )
            {
            m_StructFloat = EditorGUILayout . FloatField ( "Float" , m_StructFloat ) ;
            }
            }
            [ Serializable ]
            public class SerializeMe
            {
            [ SerializeField ]
            private NestedClass m_Class1 ;
            [ SerializeField ]
            private NestedClass m_Class2 ;
            public SerializeMe ( )
            {
            m_Class1 = ScriptableObject . CreateInstance ( ) ;
            m_Class2 = m_Class1 ;
            }
            public void OnGUI ( )
            {
            m_Class1 . OnGUI ( ) ;
            m_Class2 . OnGUI ( ) ;
            }
            }

            The three changes of note here are that:

            这里需要注意的三个变化是:

              These simple changes mean that the instance of the NestedClass will only be serialized once, with each of the references to the class pointing to the same one.

              这些简单的更改意味着NestedClass的实例将仅被序列化一次,对该类的每个引用都指向同一实例。

              ScriptableObject Initialization So now we know that for complex data structures where external referencing is needed it is a good idea to use ScriptableObjects. But what is the correct way to work with ScriptableObjects from user code? The first thing to examine is HOW scriptable objects are initialized, especially from the Unity serialization system.

              ScriptableObject初始化因此,现在我们知道,对于需要外部引用的复杂数据结构,使用ScriptableObjects是一个好主意。 但是从用户代码使用ScriptableObjects的正确方法是什么? 首先要检查的是如何初始化可脚本编写的对象,尤其是从Unity序列化系统初始化的对象。

                Working with this knowledge there are some things that we can say:

                利用这些知识,我们可以说一些事情:

                  Lets make some changes to the ‘SerializeMe’ class so that it is a ScriptableObject. This will allow us to see the correct initialization pattern for ScriptableObjects.

                  让我们对'SerializeMe'类进行一些更改,使其成为ScriptableObject。 这将使我们能够看到ScriptableObjects的正确初始化模式。

                  1

                  2
                  3
                  4
                  5
                  6
                  7
                  8
                  9
                  10
                  11
                  12
                  13
                  14
                  15
                  16
                  17
                  18
                  19
                  20
                  21
                  22
                  23
                  24
                  25
                  26
                  27
                  28
                  29
                  // also updated the Window to call CreateInstance instead of the constructor
                  using System;
                  using UnityEngine;
                  [Serializable]
                  public class SerializeMe : ScriptableObject
                  {
                  [SerializeField]
                  private NestedClass m_Class1;
                  [SerializeField]
                  private NestedClass m_Class2;
                  public void OnEnable ()
                  {
                  hideFlags = HideFlags.HideAndDontSave;
                  if (m_Class1 == null)
                  {
                  m_Class1 = CreateInstance ();
                  m_Class2 = m_Class1;
                  }
                  }
                  public void OnGUI ()
                  {
                  m_Class1.OnGUI();
                  m_Class2.OnGUI();
                  }
                  }

                  1

                  2
                  3
                  4
                  5
                  6
                  7
                  8
                  9
                  10
                  11
                  12
                  13
                  14
                  15
                  16
                  17
                  18
                  19
                  20
                  21
                  22
                  23
                  24
                  25
                  26
                  27
                  28
                  29
                  // also updated the Window to call CreateInstance instead of the constructor
                  using System ;
                  using UnityEngine ;
                  [ Serializable ]
                  public class SerializeMe : ScriptableObject
                  {
                  [ SerializeField ]
                  private NestedClass m_Class1 ;
                  [ SerializeField ]
                  private NestedClass m_Class2 ;
                  public void OnEnable ( )
                  {
                  hideFlags = HideFlags . HideAndDontSave ;
                  if ( m_Class1 == null )
                  {
                  m_Class1 = CreateInstance ( ) ;
                  m_Class2 = m_Class1 ;
                  }
                  }
                  public void OnGUI ( )
                  {
                  m_Class1 . OnGUI ( ) ;
                  m_Class2 . OnGUI ( ) ;
                  }
                  }

                  On the surface it seems that we have not really changed this class much, it now inherits from ScriptableObject and instead of using a constructor has an OnEnable(). The important part to take note of is slightly more subtle… OnEnable() is called AFTER serialization; because of this we can see if the [SerializedFields] are null or not. If they are null it indicates that this is the first initialization, and we need to construct the instances. If they are not null then they have been loaded into memory, and do NOT need to be constructed. It is common in OnEnable() to also call a custom Initialization function to configure any private / non serialized fields on the object, much like you would do in a constructor.

                  从表面上看,我们似乎并没有真正改变此类,它现在是从ScriptableObject继承的,而不是使用具有OnEnable()的构造函数。 需要注意的重要部分更加微妙……OnEnable()称为AFTER序列化; 因此,我们可以查看[SerializedFields]是否为null。 如果它们为null,则表明这是第一次初始化,我们需要构造实例。 如果它们不为null,则它们已被加载到内存中,不需要构造。 在OnEnable()中,通常也调用自定义的初始化函数来配置对象上的任何私有/非序列化字段,就像在构造函数中一样。

                  HideFlags In the examples using ScriptableObjects you will notice that we are setting the ‘hideFlags’ on the object to HideFlags.HideAndDontSave. This is a special setup that is required when writing custom data structures that have no root in the scene. This is to get around how scene loading works in Unity.

                  HideFlags在使用ScriptableObjects的示例中,您会注意到我们将对象上的“ hideFlags”设置为HideFlags.HideAndDontSave。 这是编写场景中没有根的自定义数据结构时所需的特殊设置。 这是为了解决场景加载在Unity中的工作方式。

                  When a scene is loaded internally unity calls Resources.UnloadUnusedAssets. If nothing is referencing an asset the garbage collector will find it. The GC uses the scene as ‘the root’ and traverses the hierarchy to see what can get GC’d. Setting the HideAndDontSave flag on a ScriptableObject tells Unity to consider that object as a root object. Because of this it will not just disappear because of an assembly reload. The object can still be destroyed by calling Destroy().

                  当内部加载场景时,统一调用Resources.UnloadUnusedAssets。 如果没有东西引用资产,则垃圾收集器将找到它。 GC使用场景作为“根”,并遍历层次结构以查看可以得到GC的内容。 在ScriptableObject上设置HideAndDontSave标志可以使Unity将该对象视为根对象。 因此,它不仅会因为装配件重载而消失。 仍然可以通过调用Destroy()销毁该对象。

                  Some ScriptableObject Rules

                  一些ScriptableObject规则

                    Concrete Array Serialization Lets have a look at a simple example that serializes a range of concrete classes.

                    具体数组序列化让我们看一个简单的示例,该序列化一系列具体类。

                    1

                    2
                    3
                    4
                    5
                    6
                    7
                    8
                    9
                    10
                    11
                    12
                    13
                    14
                    15
                    16
                    17
                    18
                    19
                    20
                    21
                    22
                    23
                    24
                    25
                    26
                    27
                    28
                    29
                    30
                    31
                    32
                    33
                    34
                    35
                    using System;
                    using System.Collections.Generic;
                    using UnityEditor;
                    using UnityEngine;
                    [Serializable]
                    public class BaseClass
                    {
                    [SerializeField]
                    private int m_IntField;
                    public void OnGUI() {m_IntField = EditorGUILayout.IntSlider ("IntField", m_IntField, 0, 10);}
                    }
                    [Serializable]
                    public class SerializeMe : ScriptableObject
                    {
                    [SerializeField]
                    private List m_Instances;
                    public void OnEnable ()
                    {
                    hideFlags = HideFlags.HideAndDontSave;
                    if (m_Instances == null)
                    m_Instances = new List ();
                    }
                    public void OnGUI ()
                    {
                    foreach (var instance in m_Instances)
                    instance.OnGUI ();
                    if (GUILayout.Button ("Add Simple"))
                    m_Instances.Add (new BaseClass ());
                    }
                    }

                    1

                    2
                    3
                    4
                    5
                    6
                    7
                    8
                    9
                    10
                    11
                    12
                    13
                    14
                    15
                    16
                    17
                    18
                    19
                    20
                    21
                    22
                    23
                    24
                    25
                    26
                    27
                    28
                    29
                    30
                    31
                    32
                    33
                    34
                    35
                    using System ;
                    using System . Collections . Generic ;
                    using UnityEditor ;
                    using UnityEngine ;
                    [ Serializable ]
                    public class BaseClass
                    {
                    [ SerializeField ]
                    private int m_IntField ;
                    public void OnGUI ( ) { m_IntField = EditorGUILayout . IntSlider ( "IntField" , m_IntField , 0 , 10 ) ; }
                    }
                    [ Serializable ]
                    public class SerializeMe : ScriptableObject
                    {
                    [ SerializeField ]
                    private List m_Instances ;
                    public void OnEnable ( )
                    {
                    hideFlags = HideFlags . HideAndDontSave ;
                    if ( m_Instances == null )
                    m_Instances = new List ( ) ;
                    }
                    public void OnGUI ( )
                    {
                    foreach ( var instance in m_Instances )
                    instance . OnGUI ( ) ;
                    if ( GUILayout . Button ( "Add Simple" ) )
                    m_Instances . Add ( new BaseClass ( ) ) ;
                    }
                    }

                    This basic example has a list of BaseClasses, by clicking the ‘Add Simple’ button it creates an instance and adds it to the list. Due to the SerializeMe class being configured properly for serialization (as discussed before) it ‘just works’. Unity sees that the List is marked for serialization and serializes each of the List elements.

                    这个基本示例包含一个BaseClasses列表,通过单击“ Add Simple”按钮,它创建一个实例并将其添加到列表中。 由于为串行化正确配置了SerializeMe类(如前所述),它“可以正常工作”。 Unity看到列表已标记为要序列化,并序列化了每个List元素。

                    General Array Serialization Lets modify the example to serialize a list that contains members of a base class and child class:

                    常规数组序列化让我们修改示例以序列化包含基类和子类成员的列表:

                    1

                    2
                    3
                    4
                    5
                    6
                    7
                    8
                    9
                    10
                    11
                    12
                    13
                    14
                    15
                    16
                    17
                    18
                    19
                    20
                    21
                    22
                    23
                    24
                    25
                    26
                    27
                    28
                    29
                    30
                    31
                    32
                    33
                    34
                    35
                    36
                    37
                    38
                    39
                    40
                    41
                    42
                    43
                    44
                    45
                    46
                    47
                    48
                    49
                    50
                    using System;
                    using System.Collections.Generic;
                    using UnityEditor;
                    using UnityEngine;
                    [Serializable]
                    public class BaseClass
                    {
                    [SerializeField]
                    private int m_IntField;
                    public virtual void OnGUI() { m_IntField = EditorGUILayout.IntSlider("IntField", m_IntField, 0, 10); }
                    }
                    [Serializable]
                    public class ChildClass : BaseClass
                    {
                    [SerializeField]
                    private float m_FloatField;
                    public override void OnGUI()
                    {
                    base.OnGUI ();
                    m_FloatField = EditorGUILayout.Slider("FloatField", m_FloatField, 0f, 10f);
                    }
                    }
                    [Serializable]
                    public class SerializeMe : ScriptableObject
                    {
                    [SerializeField]
                    private List m_Instances;
                    public void OnEnable ()
                    {
                    if (m_Instances == null)
                    m_Instances = new List ();
                    hideFlags = HideFlags.HideAndDontSave;
                    }
                    public void OnGUI ()
                    {
                    foreach (var instance in m_Instances)
                    instance.OnGUI ();
                    if (GUILayout.Button ("Add Base"))
                    m_Instances.Add (new BaseClass ());
                    if (GUILayout.Button ("Add Child"))
                    m_Instances.Add (new ChildClass ());
                    }
                    }

                    1

                    2
                    3
                    4
                    5
                    6
                    7
                    8
                    9
                    10
                    11
                    12
                    13
                    14
                    15
                    16
                    17
                    18
                    19
                    20
                    21
                    22
                    23
                    24
                    25
                    26
                    27
                    28
                    29
                    30
                    31
                    32
                    33
                    34
                    35
                    36
                    37
                    38
                    39
                    40
                    41
                    42
                    43
                    44
                    45
                    46
                    47
                    48
                    49
                    50
                    using System ;
                    using System . Collections . Generic ;
                    using UnityEditor ;
                    using UnityEngine ;
                    [ Serializable ]
                    public class BaseClass
                    {
                    [ SerializeField ]
                    private int m_IntField ;
                    public virtual void OnGUI ( ) { m_IntField = EditorGUILayout . IntSlider ( "IntField" , m_IntField , 0 , 10 ) ; }
                    }
                    [ Serializable ]
                    public class ChildClass : BaseClass
                    {
                    [ SerializeField ]
                    private float m_FloatField ;
                    public override void OnGUI ( )
                    {
                    base . OnGUI ( ) ;
                    m_FloatField = EditorGUILayout . Slider ( "FloatField" , m_FloatField , 0f , 10f ) ;
                    }
                    }
                    [ Serializable ]
                    public class SerializeMe : ScriptableObject
                    {
                    [ SerializeField ]
                    private List m_Instances ;
                    public void OnEnable ( )
                    {
                    if ( m_Instances == null )
                    m_Instances = new List ( ) ;
                    hideFlags = HideFlags . HideAndDontSave ;
                    }
                    public void OnGUI ( )
                    {
                    foreach ( var instance in m_Instances )
                    instance . OnGUI ( ) ;
                    if ( GUILayout . Button ( "Add Base" ) )
                    m_Instances . Add ( new BaseClass ( ) ) ;
                    if ( GUILayout . Button ( "Add Child" ) )
                    m_Instances . Add ( new ChildClass ( ) ) ;
                    }
                    }

                    The example has been extended so that there is now a ChildClass, but we are serializing using the BaseClass. If you create a few instance of the ChildClass and the BaseClass they will render properly. Issues arise when they are placed through an assembly reload. After the reload completes every instance will be a BaseClass, with all the ChildClass information stripped. The instances are being sheared by the serialization system.

                    对该示例进行了扩展,以便现在有一个ChildClass,但是我们正在使用BaseClass进行序列化。 如果创建ChildClass和BaseClass的一些实例,它们将正确呈现。 通过装配件重装放置它们时会出现问题。 重新加载完成后,每个实例将是一个BaseClass,所有ChildClass信息都将被剥离。 实例被序列化系统剪切。

                    The way to work around this limitation of the serialization system is to once again use ScriptableObjects:

                    解决序列化系统这一限制的方法是再次使用ScriptableObjects:

                    1

                    2
                    3
                    4
                    5
                    6
                    7
                    8
                    9
                    10
                    11
                    12
                    13
                    14
                    15
                    16
                    17
                    18
                    19
                    20
                    21
                    22
                    23
                    24
                    25
                    26
                    27
                    28
                    29
                    30
                    31
                    32
                    33
                    34
                    35
                    36
                    37
                    38
                    39
                    40
                    41
                    42
                    43
                    44
                    45
                    46
                    47
                    48
                    49
                    50
                    51
                    52
                    53
                    54
                    55
                    56
                    57
                    using System;
                    using System.Collections.Generic;
                    using UnityEngine;
                    using UnityEditor;
                    [Serializable]
                    public class MyBaseClass : ScriptableObject
                    {
                    [SerializeField]
                    protected int m_IntField;
                    public void OnEnable() { hideFlags = HideFlags.HideAndDontSave; }
                    public virtual void OnGUI ()
                    {
                    m_IntField = EditorGUILayout.IntSlider("IntField", m_IntField, 0, 10);
                    }
                    }
                    [Serializable]
                    public class ChildClass : MyBaseClass
                    {
                    [SerializeField]
                    private float m_FloatField;
                    public override void OnGUI()
                    {
                    base.OnGUI ();
                    m_FloatField = EditorGUILayout.Slider("FloatField", m_FloatField, 0f, 10f);
                    }
                    }
                    [Serializable]
                    public class SerializeMe : ScriptableObject
                    {
                    [SerializeField]
                    private List m_Instances;
                    public void OnEnable ()
                    {
                    if (m_Instances == null)
                    m_Instances = new List();
                    hideFlags = HideFlags.HideAndDontSave;
                    }
                    public void OnGUI ()
                    {
                    foreach (var instance in m_Instances)
                    instance.OnGUI ();
                    if (GUILayout.Button ("Add Base"))
                    m_Instances.Add(CreateInstance());
                    if (GUILayout.Button ("Add Child"))
                    m_Instances.Add(CreateInstance());
                    }
                    }

                    1

                    2
                    3
                    4
                    5
                    6
                    7
                    8
                    9
                    10
                    11
                    12
                    13
                    14
                    15
                    16
                    17
                    18
                    19
                    20
                    21
                    22
                    23
                    24
                    25
                    26
                    27
                    28
                    29
                    30
                    31
                    32
                    33
                    34
                    35
                    36
                    37
                    38
                    39
                    40
                    41
                    42
                    43
                    44
                    45
                    46
                    47
                    48
                    49
                    50
                    51
                    52
                    53
                    54
                    55
                    56
                    57
                    using System ;
                    using System . Collections . Generic ;
                    using UnityEngine ;
                    using UnityEditor ;
                    [ Serializable ]
                    public class MyBaseClass : ScriptableObject
                    {
                    [ SerializeField ]
                    protected int m_IntField ;
                    public void OnEnable ( ) { hideFlags = HideFlags . HideAndDontSave ; }
                    public virtual void OnGUI ( )
                    {
                    m_IntField = EditorGUILayout . IntSlider ( "IntField" , m_IntField , 0 , 10 ) ;
                    }
                    }
                    [ Serializable ]
                    public class ChildClass : MyBaseClass
                    {
                    [ SerializeField ]
                    private float m_FloatField ;
                    public override void OnGUI ( )
                    {
                    base . OnGUI ( ) ;
                    m_FloatField = EditorGUILayout . Slider ( "FloatField" , m_FloatField , 0f , 10f ) ;
                    }
                    }
                    [ Serializable ]
                    public class SerializeMe : ScriptableObject
                    {
                    [ SerializeField ]
                    private List m_Instances ;
                    public void OnEnable ( )
                    {
                    if ( m_Instances == null )
                    m_Instances = new List ( ) ;
                    hideFlags = HideFlags . HideAndDontSave ;
                    }
                    public void OnGUI ( )
                    {
                    foreach ( var instance in m_Instances )
                    instance . OnGUI ( ) ;
                    if ( GUILayout . Button ( "Add Base" ) )
                    m_Instances . Add ( CreateInstance ( ) ) ;
                    if ( GUILayout . Button ( "Add Child" ) )
                    m_Instances . Add ( CreateInstance ( ) ) ;
                    }
                    }

                    After running this, changing some values, and reloading assemblies you will notice that ScriptableObjects are safe to use in arrays even if you are serializing derived types. The reason is that when you serialize a standard [Serializable] class it is serialized ‘in place’, but a ScriptableObject is serialized externally and the reference inserted into the collection. The shearing occurs because the type can not be properly be serialized as the serialization system thinks it is of the base type.

                    运行此命令,更改某些值并重新加载程序集后,您将注意到即使在序列化派生类型时,ScriptableObject也可以在数组中安全使用。 原因是,当您序列化一个标准的[Serializable]类时,它被“就地”序列化了,但是一个ScriptableObject在外部被序列化了,并将引用插入了集合中。 发生剪切是因为无法正确序列化该类型,因为序列化系统认为该类型是基本类型。

                    Serializing Abstract Classes So now we have seen that it’s possible to serialize a general list (so long as the members are of type ScriptableObject). Lets see how abstract classes behave:

                    序列化抽象类因此,现在我们已经看到可以序列化一个常规列表(只要成员的类型为ScriptableObject)。 让我们看一下抽象类的行为:

                    1

                    2
                    3
                    4
                    5
                    6
                    7
                    8
                    9
                    10
                    11
                    12
                    13
                    14
                    15
                    16
                    17
                    18
                    19
                    20
                    21
                    22
                    23
                    24
                    25
                    26
                    27
                    28
                    29
                    30
                    31
                    32
                    33
                    34
                    35
                    36
                    37
                    38
                    39
                    40
                    41
                    42
                    43
                    44
                    45
                    46
                    47
                    48
                    49
                    50
                    51
                    52
                    using System;
                    using UnityEditor;
                    using System.Collections.Generic;
                    using UnityEngine;
                    [Serializable]
                    public abstract class MyBaseClass : ScriptableObject
                    {
                    [SerializeField]
                    protected int m_IntField;
                    public void OnEnable() { hideFlags = HideFlags.HideAndDontSave; }
                    public abstract void OnGUI ();
                    }
                    [Serializable]
                    public class ChildClass : MyBaseClass
                    {
                    [SerializeField]
                    private float m_FloatField;
                    public override void OnGUI()
                    {
                    m_IntField = EditorGUILayout.IntSlider("IntField", m_IntField, 0, 10);
                    m_FloatField = EditorGUILayout.Slider("FloatField", m_FloatField, 0f, 10f);
                    }
                    }
                    [Serializable]
                    public class SerializeMe : ScriptableObject
                    {
                    [SerializeField]
                    private List m_Instances;
                    public void OnEnable ()
                    {
                    if (m_Instances == null)
                    m_Instances = new List();
                    hideFlags = HideFlags.HideAndDontSave;
                    }
                    public void OnGUI ()
                    {
                    foreach (var instance in m_Instances)
                    instance.OnGUI ();
                    if (GUILayout.Button ("Add Child"))
                    m_Instances.Add(CreateInstance());
                    }
                    }

                    1

                    2
                    3
                    4
                    5
                    6
                    7
                    8
                    9
                    10
                    11
                    12
                    13
                    14
                    15
                    16
                    17
                    18
                    19
                    20
                    21
                    22
                    23
                    24
                    25
                    26
                    27
                    28
                    29
                    30
                    31
                    32
                    33
                    34
                    35
                    36
                    37
                    38
                    39
                    40
                    41
                    42
                    43
                    44
                    45
                    46
                    47
                    48
                    49
                    50
                    51
                    52
                    using System ;
                    using UnityEditor ;
                    using System . Collections . Generic ;
                    using UnityEngine ;
                    [ Serializable ]
                    public abstract class MyBaseClass : ScriptableObject
                    {
                    [ SerializeField ]
                    protected int m_IntField ;
                    public void OnEnable ( ) { hideFlags = HideFlags . HideAndDontSave ; }
                    public abstract void OnGUI ( ) ;
                    }
                    [ Serializable ]
                    public class ChildClass : MyBaseClass
                    {
                    [ SerializeField ]
                    private float m_FloatField ;
                    public override void OnGUI ( )
                    {
                    m_IntField = EditorGUILayout . IntSlider ( "IntField" , m_IntField , 0 , 10 ) ;
                    m_FloatField = EditorGUILayout . Slider ( "FloatField" , m_FloatField , 0f , 10f ) ;
                    }
                    }
                    [ Serializable ]
                    public class SerializeMe : ScriptableObject
                    {
                    [ SerializeField ]
                    private List m_Instances ;
                    public void OnEnable ( )
                    {
                    if ( m_Instances == null )
                    m_Instances = new List ( ) ;
                    hideFlags = HideFlags . HideAndDontSave ;
                    }
                    public void OnGUI ( )
                    {
                    foreach ( var instance in m_Instances )
                    instance . OnGUI ( ) ;
                    if ( GUILayout . Button ( "Add Child" ) )
                    m_Instances . Add ( CreateInstance ( ) ) ;
                    }
                    }

                    This code much like the previous example works. But it IS dangerous. Lets see why.

                    此代码非常类似于前面的示例。 但这很危险。 让我们看看为什么。

                    The function CreateInstance<>() expects a type that inherits from ScriptableObject, the class ‘MyBaseClass’ does in fact inherit from ScriptableObject. This means that it’s possible to add an instance of the abstract class MyBaseClass to the m_Instances array. If you do this and then try and access an abstract method bad things will happen because there is no implementation of that function. In this specific case that would be the OnGUI method.

                    函数CreateInstance <>()期望从ScriptableObject继承的类型,而类“ MyBaseClass”实际上从ScriptableObject继承。 这意味着可以将抽象类MyBaseClass的实例添加到m_Instances数组。 如果执行此操作,然后尝试访问抽象方法,则将发生不好的事情,因为该函数没有实现。 在这种特定情况下,将是OnGUI方法。

                    Using abstract classes as the serialized type for lists and fields DOES work, so long as they inherit from ScriptableObject, but it is not a recommended practice. Personally I think it’s better to use concrete classes with empty virtual methods. This ensures that things will not go bad for you.

                    只要抽象类是从ScriptableObject继承的,就可以使用抽象类作为列表和字段的序列化类型,但是不建议这样做。 我个人认为最好将具体类与空虚方法一起使用。 这样可以确保事情不会对您不利。

                    When do ScriptableObjects get persisted into scene / prefab files? GameObjects and their components are saved into a scene by default. Asset types (Materials / Meshes / AnimationClip / SerializedObject’s) that are created from code are saved in the scene so long as a game object or their components in the scene references it.

                    何时将ScriptableObjects保留到场景/预制文件中? GameObject及其组件默认情况下保存到场景中。 从代码创建的资产类型(材料/网格/动画剪辑/序列化对象)将保存在场景中,只要游戏对象或其场景中的组件对其进行引用即可。

                    Asset types can also be explicitly marked as assets using AssetDatabase.CreateAsset. In that case they will not be saved in the scene but simply referenced. If an asset type or game object type is marked as HideAndDontSave it also not saved in the scene.

                    也可以使用AssetDatabase.CreateAsset将资产类型显式标记为资产。 在这种情况下,它们将不会保存在场景中,而只是被引用。 如果资产类型或游戏对象类型标记为HideAndDontSave,它也不会保存在场景中。

                    Questions?

                    有什么问题吗

                    翻译自: https://blogs.unity3d.com/2012/10/25/unity-serialization/

                    unity序列化

                    展开全文
                  • unity序列化和反序列化In the spirit of sharing more of the tech behind the scenes, and reasons why some things are the way they are, this post contains an overview of Unity’s serialization system....
                  • unity序列化工作原理和实例.docx unity序列化工作原理和实例.docx unity序列化工作原理和实例.docx unity序列化工作原理和实例.docx unity序列化工作原理和实例.docx
                  • 1、序列化就是将对象保存在文件中,在检视面板看到的就是成功序列化的内容 与序列化相关的常用的关键字有SerializeField,HideInInspector,NonSerialized,Serializable并可以组合使用。 SerializeField : 表示...
                  • 什么是序列化和反序列化(1)序列化是指把对象转换为字节序列的过程,而反序列化是指把字节序列恢复为对象的过程;. (2)序列化:对象序列化的最主要的用处就是在传递和保存对象的时候,保证对象的完整性和可传递性...
                  • 该代码为Unity Editor 使用序列化保存数据,将数据显示在Inspector 面板上的操作
                  • Unity 序列化问题

                    2018-02-07 20:14:44
                    序列化问题 : 可以参考 ...但是如果一个可序列化的类,在运行的时候才给他引用那么它就不会被序列化。 看下面两个脚本测试的代码: using UnityEngine; using System.Collection
                  • Unity 序列化 总结

                    2015-03-16 19:29:00
                    查找了 Script Serialization ... 自定义序列化及例子: http://docs.unity3d.com/ScriptReference/ISerializationCallbackReceiver.OnBeforeSerialize.html 和U...
                  • Unity序列化和持久化

                    2016-04-24 11:23:28
                    据我所知unity Serialization对于基本数据类型非常好用,但处理复类型时就有些基础缺陷了。...Unity内置的持久策略是通过“m_LocalIdentfierInFile”(将检视面板视图切换为Debug模式即可看到该字段)来连接场景文件
                  • Unity 序列化类型总结

                    2019-10-31 11:42:56
                    unity序列化脚本时,它只会序列化公有字段,如果想要序列化私有字段,就需要为该字段添加SerializeField特性,该特性用于强制序列化私有字段; 序列化的目的是为了进行本地存储,unity将会序列化所有的脚本化组件...
                  • Unity序列化一些内容

                    2019-07-03 17:25:12
                    序列化又称串行化,是.NET运行时环境用来支持用户定义类型的流化的机制。...Unity序列化 在Unity中,在检视面板中可以看到的,就是被成功序列化了的参数。与序列化相关的常用的关键字有Seriali...
                  • Unity序列化全面解析

                    2019-08-16 10:44:32
                    这篇博客讲得非常全面。 感谢大大!
                  • Unity 序列化的问题

                    2020-06-19 22:30:41
                    Unity 序列化 当我用父类引用子类的实例时,序列化只会保存父类的数据。 解决这种问题只能使用Json序列化 继承unity序列化接口,用一个字符串保存真正的值,在序列化之前和序列化之后,对这个字符串进行还原。...
                  • PlayerPrefs(数据持久)用于本地持久保存与读取的类,工作原理很简单,以键值对的形式将数据保存在文件中,然后程序可以根据这个名称取出上次保存的数值(注:数据通过键名来读取,当值不存在时,返回默认值)。...

                  空空如也

                  1 2 3 4 5 ... 20
                  收藏数 1,335
                  精华内容 534
                  关键字:

                  unity序列化