Search Unity

  1. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

4.5 - Serialization Depth

Discussion in 'Editor & General Support' started by LightStriker, May 27, 2014.

  1. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,717
    You mean it becomes unresponsive?
     
  2. Grespon

    Grespon

    Joined:
    Apr 13, 2012
    Posts:
    388
    No.. it really pauses .. I need to unpause
     
  3. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,717
    Might be something else then.

    I updated my first post with details and workaround.
     
  4. tswalk

    tswalk

    Joined:
    Jul 27, 2013
    Posts:
    1,109
    good to know, thanks for the detailed recap!... much appreciated.
     
  5. Grespon

    Grespon

    Joined:
    Apr 13, 2012
    Posts:
    388
    Solved. Unity 4.5 seems to have 'Error Pause' turned on by default.
     
  6. metinevren

    metinevren

    Joined:
    May 17, 2014
    Posts:
    28
    I get the same error but with "Transition"s. What can I do?

    Serialization depth limit exceeded at '::Transition'. There may be an object composition cycle in one or more of your serialized classes.
    UnityEditor.HostView:OnGUI()

    I am not using Transition variables in my code. I only have Animators. Should I ignore it?
     
  7. superpig

    superpig

    Drink more water! Unity Technologies

    Joined:
    Jan 16, 2011
    Posts:
    4,642
    It sounds like there is a script somewhere in your project that defines a 'Transition' class. You might want to check any asset store packages you're using. As far as I know there's no Transition class built into Unity.
     
  8. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,717
    Sadly, the error only list the type, and not the name of the faulty field.
     
  9. makeshiftwings

    makeshiftwings

    Joined:
    May 28, 2011
    Posts:
    3,350
    Can we get an official response on whether or not the serialization of private/protected fields is a bug? I don't really want to go through all my code and asset store plugins and add "Nonserialized" to private fields if it's something that is going to be fixed sooner or later. It was mentioned that Unity "sometimes" serializes the private fields... is this "sometimes" actually "all the time" and is it intentional or unintentional?
     
  10. Nims

    Nims

    Joined:
    Nov 11, 2013
    Posts:
    86
    @LightStriker I am interested in how you get a hold of the info you displayed in your previous post:
    Code (csharp):
    1.     Mono: successfully reloaded assembly
    2.     - Completed reload, in  0.914 seconds
    3.     System memory in use before: 48.2 MB.
    4.     Unloading 149 Unused Serialized files (Serialized files now loaded: 0 / Dirty serialized files: 0)
    5.     System memory in use after: 34.8 MB.
    6.      
    7.     Unloading 200 unused Assets to reduce memory usage. Loaded Objects now: 2195.
    8.     Total: 15.206539 ms (FindLiveObjects: 0.143984 ms CreateObjectMapping: 0.028978 ms MarkObjects: 2.562143 ms  DeleteObjects: 1.711516 ms)
    Also would be interested in knowing how people are tracking down their serialization loops as the error doesn't really direct you to where it's occurring.
     
  11. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,717
    This info is part of the Editor Log, which you can find at %localappdata%\Unity\Editor\ on Window.

    That specific text is input in the log when you press play, and occurs when the assembly is reloaded.

    As for tracking the entry point of a serialization loop... No luck. It's a hit or miss game where you have to know your serialization and your class hierarchy. Took me hours to find the exact fields that were causing issues, and even more hours to find a workaround. The only information you have is the type of the field that should give you issues.
     
  12. ParkyRander

    ParkyRander

    Joined:
    Jun 1, 2014
    Posts:
    8
    For what its worth, here's some test I did after hitting the same problem. BTW Apologies for the formatting, first time post


    Code (csharp):
    1. // NOT OK
    2. // Serialization depth limit exceeded at '::TestClass1'. There may be an object composition cycle in one or more of your serialized classes.
    3. [System.Serializable]
    4. public class TestClass1
    5. {
    6.     public List<TestClass1> Children
    7.     {
    8.         get;
    9.         set;
    10.     }
    11. }
    12.  
    13. // NOT OK
    14. // Serialization depth limit exceeded at '::TestClass2'. There may be an object composition cycle in one or more of your serialized classes.
    15. [System.Serializable]
    16. public class TestClass2
    17. {
    18.     public List<TestClass2> Children;
    19. }
    20.  
    21. // NOT OK
    22. // Won't compile
    23. // Assets/Plugins/TestClass.cs(26,17): error CS0592: The attribute `System.NonSerializedAttribute' is not valid on this declaration type. It is valid on `field' declarations only
    24. //[System.Serializable]
    25. //public class TestClass3
    26. //{
    27. //  [System.NonSerialized]
    28. //  public List<TestClass3> Children
    29. //  {
    30. //      get;
    31. //      set;
    32. //  }
    33. //}
    34.  
    35.  
    36. // OK
    37. [System.Serializable]
    38. public class TestClass4
    39. {
    40.     [System.NonSerialized]
    41.     public List<TestClass4> Children;
    42. }
    43.  
    44.  
    45. // OK
    46. [System.Serializable]
    47. public class TestClass5
    48. {
    49.     [System.NonSerialized]
    50.     List<TestClass5> m_children;
    51.  
    52.     public List<TestClass5> Children
    53.     {
    54.         get { return m_children; }
    55.         set { m_children = value; }
    56.     }
    57. }
     
  13. superpig

    superpig

    Drink more water! Unity Technologies

    Joined:
    Jan 16, 2011
    Posts:
    4,642
    The TestClass2 example there should report the error, fwiw.

    Seems like maybe the code generating the warning isn't checking that MeberInfo.MemberType == MemberType.Field.
     
  14. makeshiftwings

    makeshiftwings

    Joined:
    May 28, 2011
    Posts:
    3,350
    Well, if the aforementioned bug of serializing private and protected fields is happening, then it would make sense that Unity is also accidentally serializing the hidden private backing variable for auto-properties. Example #2 would have a private but not NonSerialized backing var while example 5 explicitly states the backing var and marks it NonSerialized.

    So... yeah, I'm still very interested to know if Unity is just always serializing all private variables and whether or not that will be fixed.
     
  15. superpig

    superpig

    Drink more water! Unity Technologies

    Joined:
    Jan 16, 2011
    Posts:
    4,642
    Example 2 doesn't use properties. You're right about auto-generated backing fields being a possible contributor to the problem, though.
     
  16. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,717
    Only that Example #2 is not a properly. It's a field. Autogenerated properties is another thing... Frankly, I never use them, but it's clear that any flag put on the property isn't passed down to the backing field.
     
  17. makeshiftwings

    makeshiftwings

    Joined:
    May 28, 2011
    Posts:
    3,350
    Sorry, I meant Example #1, the one with the auto-property. Oops.
     
  18. Rico21745

    Rico21745

    Joined:
    Apr 25, 2012
    Posts:
    409
    Just upgraded to 4.5 and saw hundreds of these errors. In theory sure it sounds fine... however, what use is there telling me about these potential issues if I'm not told where they occur? My project is massive at this point and trying to find the root of these errors without any hints is pointless.

    Double clicking the messages does nothing. I expected Monodevelop to bring up the offending line, or Unity to at least highlight the class file in the Project view. The error messages themselves are incredibly generic, to the point of uselessness.

    For example: I get an console full of these messages $Capture.JPG
     
  19. Tak

    Tak

    Joined:
    Mar 8, 2010
    Posts:
    1,001
    If I recall correctly, when entering play mode, when reloading script assemblies during play mode, probably some other, similar cases. This is intentional behavior.

    Since several people have asked again, I'll repeat. This behavior has always existed - in Unity 4.5, we added a message letting you know it was happening.
     
  20. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,717
    Any reason why private fields are being serialized in play mode change, but not in data save? Why the two different behaviour?

    Why have two different behaviours that no documentation ever noted? I spent days trying to track down the issue with my data freezing the editor for minutes anytime we press play without anybody ever saying that private fields were serialized if not explicitly flagged as NonSerialized!
     
  21. AlkisFortuneFish

    AlkisFortuneFish

    Joined:
    Apr 26, 2013
    Posts:
    964
    One thing I'd like to add is that our project was suffering from this and fixing it reduced the time it took for the first in-editor run after loading the project from 15s down to 3s on both 4.5 and 4.3. I didn't repeat it more than a few times, so the numbers are probably meaningless but is considerably faster, so the performance cliff Unity is talking about isn't particularly theoretical.
     
  22. Jacob-Aldridge

    Jacob-Aldridge

    Joined:
    Feb 26, 2009
    Posts:
    120
    So what about the times when this is legitimate and we use this to define children in a class? I understand that this prevents us from going past 7 levels of depth, but how can we use this pattern to create a self referencing class? It seems horribly useful to be able to do this when we want to create a parent-child relationship with the same type. What are some suggestions on how to deal with this when we need it? Is there an attribute that can override the warning?

    Code (CSharp):
    1. [Serializable]
    2. public class Test
    3. {
    4.    public String Name;
    5.  
    6.    public List<Test> Children;
    7. }
     
    Last edited: Jun 2, 2014
  23. makeshiftwings

    makeshiftwings

    Joined:
    May 28, 2011
    Posts:
    3,350
    Yes, but Debug.Log() is super slow, and adding that "message" will cause a huge slowdown when it needs to log it a thousand times every time you hit play. It's also a nearly useless message since it gives you no clue of where the problem is and no way of knowing whether or not it's an "actual" problem since there is apparently this weird serialization of private fields that doesn't actually happen in standalone builds.
     
  24. davemeta

    davemeta

    Joined:
    Jul 17, 2012
    Posts:
    17
    My "offending" class doesn't contain any of the examples mentioned here that will cause this error. It only contains primitives and getters/setters, yet error is still being triggered.

    Any ideas here?
     
  25. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    3,389
    Due to the lack of null serialization, I can understand why this would cause the error to throw:

    Code (csharp):
    1.  
    2. [Serializable]
    3. class Foo
    4. {
    5.     public Foo Next;
    6. }
    But why would this cause the error to be thrown:

    Code (csharp):
    1.  
    2. [Serializable]
    3. class Foo
    4. {
    5.     public List<Foo> Children;
    6. }
    In this case, the size of the list/array IS stored, and because the default array/list size is 0, I don't see why it would continue to recursively serialize.

    There are tons of cases where both of these design patterns are useful, and I think it's pretty ridiculous that they're not supported (without writing custom serialization code at least, which isn't too useful for asset developers that wish to target stuff earlier than 4.5). I can understand the difficulty of supporting polymorphic serialization, but why is null serialization so difficult?
     
  26. terravires

    terravires

    Joined:
    Mar 27, 2013
    Posts:
    103
    I got these too, turns out they were all from Terrain Composer. Removing the folder from your project and it goes away. Only issue is that you can't keep the "saved" data around. Even if you disabled GameObject because you then get errors about missing scripts. Not sure if there is a workaround for that.
     
    Last edited: Jun 3, 2014
  27. superpig

    superpig

    Drink more water! Unity Technologies

    Joined:
    Jan 16, 2011
    Posts:
    4,642
    One solution is to do something like:

    Code (csharp):
    1.  
    2. [Serializable]
    3. public class TestCollection
    4. {
    5.    public List<Test> Tests;
    6. }
    7.  
    8. [Serializable]
    9. public class Test
    10. {
    11.    public String name;
    12.    public List<int> ChildIndices;
    13. }
    14.  
    It requires more book-keeping but ultimately you can represent the same structure.

    If you make the child non-serialized then you'll avoid the problem (and so the warning will go away).
     
    Jacob-Aldridge likes this.
  28. Immanuel-Scholz

    Immanuel-Scholz

    Joined:
    Jun 8, 2013
    Posts:
    221
    Adding "a" message is unfortunately wrong. You were adding dozends of thousands of messages, crashing the editor occasionally (out of memory) and making playmode and assembly reloads very slow.

    Yes, fixing them by removing dependencies (mostly by distributing NonSerialized to all private fields) will be the way to go. And I am thankful, that unity brought up the issue, but until then we can not use 4.5 because of the crashes and lags this tiny feature introduced (or at least until we or the corresponding asset store package owners fixed most of the cases).
     
  29. Tak

    Tak

    Joined:
    Mar 8, 2010
    Posts:
    1,001
    One message is printed for each object where we pass the maximum recursion depth.

    If you're seeing dozens of thousands of messages in Unity 4.5, that means you're taking dozens of thousands of performance hits in your project in Unity 4.3. Many bug reports about assembly reload times, out-of-memory errors, "hangs", etc. were traced back to this.
     
  30. Rico21745

    Rico21745

    Joined:
    Apr 25, 2012
    Posts:
    409
    That's fine but I think some of us have two issues with all of this:

    1) The messages are nigh impossible to use to fix these issues, all they do is say "hey we don't like your code, too bad" hundreds of times. It doesn't provide real meaningful and useful feedback. I mean when it tells me it's a value type and it doesn't tell me which class or where, that's a needle in a haystack. We have thousands and thousands of lines of code, both from our own assets and Asset Store packages. How are we ever to find out what's causing this other than scrubbing through each line of code? If Unity is finding the error, why not output the location of it so that it's actually helpful? Otherwise, may as well not tell us anything and just spit put one error instead? It's equally useless in both cases, really, may as well minimize the logging.

    2) If the case of a class not being able to have itself as a member is a problem, then that's a pretty big issue. There's lots of game and AI algorithms that require this sort of relationship. Trees require this basic idea of a node having other nodes of the same type under them as children, so Unity not liking this is not a small problem, that means anyone with any tree structure ever has an issue, which is probably any game with any sort of pathfinding, or complexity beyond a Flappy Bird clone.
     
  31. superpig

    superpig

    Drink more water! Unity Technologies

    Joined:
    Jan 16, 2011
    Posts:
    4,642

    Hmm...

    It ought to be possible to detect this purely through static analysis of the serializable types in the assembly, I think? So maybe reporting it at compile time is an option?
     
  32. Immanuel-Scholz

    Immanuel-Scholz

    Joined:
    Jun 8, 2013
    Posts:
    221
    Thanks for the answer. I totally agree that these logging lines are surely not our biggest memory chunk at the moment. And I totally agree that the issue at hand is worth raising at least a console warning, so people can start cleaning up and fine-tuning their code to make their projects launch faster.

    For now, I can cope with it by reducing all our textures to 1x1, then trying to fix the errors whereever possible and finally restore the textures. Pain.. but working.. And probably worth it 10 times in the long run.. ;)


    But maybe for the next warnings, you devs can remember that it is not a trivial thing for large projects to to print one message for every game object? It CAN crash the editor if the memory consumption is already near the border.. Even a hidden registry entry to supress intern log messages would be much helpfull sometimes...


    Edit: Ah, what the brabbling... Unity 5 will come with a 64-bit editor anyway, so my puny complaints have a built-in death sentence :-D
     
    Last edited: Jun 3, 2014
  33. AlkisFortuneFish

    AlkisFortuneFish

    Joined:
    Apr 26, 2013
    Posts:
    964
    Unity likes that just fine, it does not like serializing it and it has never actually managed to. This problem is not new, it's the reason things like the A Star Pathfinding project etc. use custom serialization instead of Unity's built-in one with its limitations, what is new is the spammy warning about it, which people should be allowed to suppress IMHO.
     
  34. makeshiftwings

    makeshiftwings

    Joined:
    May 28, 2011
    Posts:
    3,350
    Can you please reply letting us know whether the serialization of all private fields and auto-properties is a bug or a feature? If it's a bug, are you guys planning on fixing it any time soon? If it's a feature, are you really saying that all Unity users and asset store products should now put [NonSerialized] on every private field and property? And can you explain what the benefit of serializing private fields by default is, other than the joy of seeing a million warning messages in the console?
     
  35. superpig

    superpig

    Drink more water! Unity Technologies

    Joined:
    Jan 16, 2011
    Posts:
    4,642
    I believe it's a feature, and is intended to better preserve state across an app domain reload (e.g. keeping your editor scripts' private variables when recompiling code, or keeping in-game private state when recompiling at runtime so things don't break so much).
     
  36. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,717
    The problem is, I never coded - game or editor class - expecting private field to stay valid between reload.

    It means there's a documented serialization for in-game scope, and an undocumented one for the editor, and that the behaviour of both is different.

    Now, out of the blue, people start added NonSerialized on all their private field, because they expected them to work that way. Wouldn't make more sense to make the serialization work the way it was advertised in the first place?
     
  37. superpig

    superpig

    Drink more water! Unity Technologies

    Joined:
    Jan 16, 2011
    Posts:
    4,642
    Yeah, I'm unconvinced by the behaviour too. It seems like it's very common to either a) use non-serializable types that break anyway when reloading assemblies or b) assume only public vars are serialised as per popular knowledge and rebuild state regardless.
     
  38. makeshiftwings

    makeshiftwings

    Joined:
    May 28, 2011
    Posts:
    3,350
    But it doesn't actually preserve private state across a reload, and there's a whole section of the docs explaining how to use [Serializable] and ScriptableObjects to preserve state. So it seems like it's just doing it for no reason. The only thing I'm really sure of is that none of us are really sure how it works, so hopefully Unity will answer eventually. ;)
     
  39. superpig

    superpig

    Drink more water! Unity Technologies

    Joined:
    Jan 16, 2011
    Posts:
    4,642
    Apparently it's supposed to:

     
  40. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,717
    Isn't such confusion just nice?

    All documentation saying private fields aren't serialized... for years... millions line of codes made in that assumption... And out of the blue "Oh wait, it does... sometimes... for some reason."

    Frankly, I would prefer if Unity's people come to do some proper explanation and maybe update their serialization documentation accordingly.
     
  41. davemeta

    davemeta

    Joined:
    Jul 17, 2012
    Posts:
    17
    Some more examples around what can cause this error would be nice, since it doesn't seem that the error is always directly related to the class it claims has a loop. Again, I am getting the error on a class that has ALL primitives. Anyone who has AudioToolkit will see this same behavior on "AudioItem".
     
  42. Immanuel-Scholz

    Immanuel-Scholz

    Joined:
    Jun 8, 2013
    Posts:
    221
    It does. Try it out!

    For example, use the following code:

    Code (csharp):
    1.  
    2. [UnityEngine.ExecuteInEditMode]
    3. public class NewBehaviourScript : UnityEngine.MonoBehaviour
    4. {
    5.    public int pub = 0;
    6.    [System.NonSerialized]int privateAndNonSerialized = 1;
    7.    int justPrivate = 1;
    8.  
    9.   void Update()
    10.   {
    11.      if (privateAndNonSerialized != pub)
    12.        print ("privateAndNonSerialized was " + privateAndNonSerialized);
    13.      if (justPrivate != pub)
    14.        print ("justPrivate was " + justPrivate);
    15.      privateAndNonSerialized = justPrivate = pub;
    16.   }
    17. }
    18.  
    Place any game object with this component in your scene, now edit the variable "pub" in the inspector. You see two log messages. So far so good.

    Clear the log and force an assembly reload (e.g. by right-clicking on any C# file and choose "Reimport").

    Voila, you see only one log line for the NonSerialized field. The assembly reload preserved the "simple" private field.

    The docs are not really "wrong" about that, they are just not complete. The docs only talk about persistation to disc into prefab and yaml files, they don't tell you all the story about persistation through assembly reloads while the editor is running. I agree, they should contain more advanced information here..
     
  43. Jacob-Aldridge

    Jacob-Aldridge

    Joined:
    Feb 26, 2009
    Posts:
    120
    Yeah, it looks like this would be a good approach to handling this issue for me. I am using my class to create an editor based data structure for the game I'm working on and find it handy to not have to deal with loading a file with all the stored data.
     
  44. makeshiftwings

    makeshiftwings

    Joined:
    May 28, 2011
    Posts:
    3,350
    Weird, I could have sworn that that exact thing did not work in previous versions of Unity, but I can't be bothered to reinstall an old version to actually test it. But I do know that at least Editor scripts (like custom editors and property drawers) would lose their private state if you entered and left play mode, which is why the docs have an entire section about how to get around it, telling you to use [Serializable] on private fields. Well, now I'm thoroughly confused.
     
  45. superpig

    superpig

    Drink more water! Unity Technologies

    Joined:
    Jan 16, 2011
    Posts:
    4,642
    For those of you who are having trouble tracking down the causes of this warning in your project, I've written a simple tool that attempts to figure out what Unity is complaining about and gives you a full 'field by field' breakdown so you can find which variables to look at.

    It's available from my Github.

    Let me know if you use it, and how it works out for you...
     
    Tethys, KyleStaves and Jacob-Aldridge like this.
  46. figbash

    figbash

    Joined:
    May 13, 2008
    Posts:
    60
    I'm not sure what to do about this error, I get it 800+ times everytime I play or compile.
    I have a custom node system, which hundreds of objects use. I don't really care about the performance penalty, and it's far too late in the game to rewrite the node system.
    I also have an editable list class (easily reorderable and works with property drawer). Basically you are saying we cannot have an editable list with another editable list inside it? This makes Unity's serialization essentially useless for our toolset!
    Is there any chance you can look into fixing this issue again rather than have your user base refactor complicated classes that already contain years of work? As of now my only real option is to continually see 800 errors in my console for a performance issue that hasn't even affected our game that's been on the app store for 3 years.

    Very frustrating :(
     
  47. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    I think it's important that serialisation depth is the way it is. If it means much faster load times and better streaming potential, better instantiation etc, then I'm sorry you'll just have to man up and fix the code :)

    Check out Richard's solution:

     
  48. figbash

    figbash

    Joined:
    May 13, 2008
    Posts:
    60
    I already know exactly where the issue is, but it's not something I can reasonably fix, unless somebody here can give a good example on how to manually do the serialization myself outside of Unity's system? My entire toolset relies on the ability to have nested EditableList instances that are serialized within ScriptableObjects, and all that data will obviously be lost if I set everything NonSerialized.

    If Unity cannot fix their serialization issues then they should at least give us the option to disable the error (which should be a warning anyway). I am more than willing to live with the performance issues as they haven't caused me any grief for years. I cannot possibly be the only person that is stuck in this situation :)
     
  49. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,717
    What is an EditableList?

    From what you told, it can be reordered... But you don't need a special class to have this functionality in the editor. If you check my signature, the Advanced Inspector offers that for all array/list, without requiring any custom class or custom editor. I'm sure you could do the same.
     
  50. cecarlsen

    cecarlsen

    Joined:
    Jun 30, 2006
    Posts:
    856
    Also getting this error.

    If I add [NonSerialized] to my variables the error dissaperes – but then they are no longer serialized. No good.
     
    Last edited: Jun 9, 2014