Search Unity

  1. Unity Asset Manager is now available in public beta. Try it out now and join the conversation here in the forums.
    Dismiss Notice

Feedback Serialization issues in 2020.1.0b1

Discussion in '2020.1 Beta' started by arkano22, Mar 13, 2020.

  1. arkano22

    arkano22

    Joined:
    Sep 20, 2012
    Posts:
    1,929
    Hi there,

    I sell assets on the Asset Store. Recently, one user reported a hard crash in Unity 2020.1.0b1 when trying to import one of our assets. The editor log immediately prior to the crash looks like this:

    Code (CSharp):
    1. Start importing Assets/Obi/Samples/RopeAndRod/SampleResources/Blueprints/Tearable cable.asset using Guid(61d053dd5abd943919947f833abd0569) Importer(-1,00000000000000000000000000000000) Serialization depth limit 7 exceeded at 'Obi::ObiConstraints`1.actor'. There may be an object composition cycle in one or more of your serialized classes.
    2.  
    3. Serialization hierarchy:
    4. 8: Obi::ObiConstraints`1.actor
    5. 7: Obi::ObiConstraints`1.source
    6. 6: Obi::ObiConstraints`1.source
    7. 5: Obi::ObiConstraints`1.source
    8. 4: Obi::ObiConstraints`1.source
    9. 3: Obi::ObiConstraints`1.source
    10. 2: Obi::ObiConstraints`1.source
    11. 1: Obi::ObiConstraints`1.source
    12.  
    13. (Filename: ./Runtime/Mono/SerializationBackend_DirectMemoryAccess/ShouldTransferField.cpp Line: 121)
    14.  
    15. Stack overflow in unmanaged: IP: 0x14532690c, fault addr: 0x7ffeea7a8ff8
    16. Stack overflow in unmanaged: IP: 0x14540456d, fault addr: 0x7ffeea7a6ff8
    17. Stack overflow in unmanaged: IP: 0x10673fea1, fault addr: 0x7ffeea7a5ff0
    18. Stack overflow in unmanaged: IP: 0x10570a50e, fault addr: 0x7ffeea7a4ff8
    19. Stack overflow in unmanaged: IP: 0x106755031, fault addr: 0x7ffeea7a3fc8
    20. Stack overflow in unmanaged: IP: 0x145326237, fault addr: 0x7ffeea7a2f98
    21. Stack overflow in unmanaged: IP: 0x145326914, fault addr: 0x7ffeea7a1ff8
    22. Stack overflow: IP: 0x10570a621, fault addr: 0x7ffeea79ffac
    23. Stacktrace:
    24. [Unity Package Manager (Upm)]
    25. Parent process [5067] was terminated
    As you can see, Unity complains of a serialization cycle, which causes a stack overflow and a crash. The cycle points to: Obi::ObiConstraints`1.source. This member variable is declared like this:

    Code (CSharp):
    1. public abstract class ObiConstraints<T> : IObiConstraints
    2. {
    3.      protected ObiConstraints<T> source;
    4. [....]
    5. }
    I would expect a protected variable to be ignored by serialization, as documented here:
    https://docs.unity3d.com/Manual/script-Serialization.html

    It is not a public variable, and it is not marked with [SerializeField].

    This behavior does not take place in 2019.2 or 2019.3, both import the asset without issue, and do not warn about a serialization cycle.

    I'd expect Unity to:
    a) ignore "source" when it comes to serialization, not attempt to serialize it as it would in fact result in a cycle.
    b) even when encountering a serialization cycle, not crash with a stack overflow.

    Am I right in assuming this is a bug? Should I file a bug report?
     
    Awarisu likes this.
  2. print_helloworld

    print_helloworld

    Joined:
    Nov 14, 2016
    Posts:
    231
    This is to do with the new ability to serialize generics, if you'd like the old behaviour then you need to mark the field with [NonSerialized].

    Though for the cycling serialization issue, that might be its own problem relating to UX.
     
  3. arkano22

    arkano22

    Joined:
    Sep 20, 2012
    Posts:
    1,929
    I'm aware that Unity can now serialize generics, but why is it necessary to explicitly mark a protected field with [NonSerialized]? I was under the impression that only public fields were only considered for serialization. Attempting to serialize a protected field (thus finding out it results in cyclic serialization) goes against the documentation, regardless of it being a generic type:

     
  4. print_helloworld

    print_helloworld

    Joined:
    Nov 14, 2016
    Posts:
    231
    If protected fields are indeed being serialized, then that sounds like a regression that could be reported as a bug.
     
    Awarisu likes this.
  5. jasonatkaruna

    jasonatkaruna

    Joined:
    Feb 26, 2019
    Posts:
    64

    "When reloading scripts, Unity restores all variables - including private variables - that fulfill the requirements for serialization, even if a variable has no SerializeField attribute. In some cases, you specifically need to prevent private variables from being restored: For example, if you want a reference to be null after reloading from scripts. In this case, use the NonSerialized attribute."

    It's not serialized in the asset, but the editor is trying to save the value for hot code reloading. See last part here: https://docs.unity3d.com/2020.1/Documentation/Manual/script-Serialization.html
     
  6. arkano22

    arkano22

    Joined:
    Sep 20, 2012
    Posts:
    1,929
    Oh, I see. So it attempts to serialize basically everything that's not explicitly marked as NonSerialized and meets the requirements for serialization (except the first one: being public) for the purpose of restoring data when hot-reloading, then when actually writing to disk it throws away all protected/private members.

    Makes sense, but causes the new generics serialization to break backwards compatibility in a lot of cases. Code written using generics that does not adhere to this rule (because it wasn't necessary at all in previous versions) will break in 2020. If it already isn't somewhere, this should be warned against in a big bold font imho, and the "serialization rules" section of the docs updated to better reflect the actual process.
     
    Last edited: Mar 20, 2020
    Havokki, JoNax97 and Awarisu like this.
  7. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    10,680
    Crashing on that is a bug. Please report it.

    As to whether it should be serialized or not: I don't think it should be. It's an abstract class that isn't marked as serializable...
     
    arkano22 and jasonatkaruna like this.