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

SerializeReference Attribute?

Discussion in '2019.3 Beta' started by SonicBloomEric, May 15, 2019.

  1. oscarAbraham

    oscarAbraham

    Joined:
    Jan 7, 2013
    Posts:
    431
    Hi. An official fix on what issue?
     
  2. BayernMaik

    BayernMaik

    Joined:
    Oct 15, 2019
    Posts:
    20
  3. bconstantin

    bconstantin

    Joined:
    Feb 4, 2019
    Posts:
    15
    Array of Enum, or List of Enum don't work. but Enum works.
    Any solutions ?
     
  4. Sangemdoko

    Sangemdoko

    Joined:
    Dec 15, 2013
    Posts:
    222
    I'm using Unity 2021.1.0f1

    I use [SerializeReference] Attribute a lot for polymorphism. Sometimes I even nest them.
    I have many custom inspectors / property drawers to add/remove the type I want in an array and/or change the object type

    But sometimes for some reason all the SerializeReferences on my components become null. After it happened a few times I think I found the cause of the problem.
    It happens when I remove/rename(including namespace) one of the object types. That's a huge problem because I'm refactoring things constantly. It would make a lot more sense if just the object with the type I refactored became null.
    But in practice ALL the [SerializeRefence] fields on the component become null. I mean ALL of them, even in other arrays with types completely irrelevant to the type I removed/renamed.

    Is this something that has been fixed in future Unity releases? Has someone expericenced the same issue?

    EDIT: doing a bit more research I came across this git readme. It has links to some threads and issue tracker for that:
    https://github.com/mackysoft/Unity-SerializeReferenceExtensions

    I was able to salvage some of my work by using the [MovedFrom] Attribute they mentioned.
    Not ideal when doing a mass namespace or assembly refactor but most definetly a life saver in a pinch
     
    Last edited: Apr 21, 2022
    phobos2077 and a436t4ataf like this.
  5. a436t4ataf

    a436t4ataf

    Joined:
    May 19, 2013
    Posts:
    1,933
    This is why - even 3 years later - I refuse to allow SerializeReference anywhere in any code in any project. I detest it. It was a feature I'd wanted for years but Unity messed it up spectactularly.

    It's not just the bugs, it's that Unity did basically nothing to tell us that they'd found these bugs. These are not 'bugs that if it affects you you might want to upgrade'. These are 'bugs that if you're using SerializeReference you MUST upgrade to the latest Unity Alpha Release today immediately or you'll probably lose data". And, of course, they're generally only fixed in alpha and beta releases.

    I don't think I'll ever be able to trust this feature. Maybe in Unity 2024 LTS - maybe! - and only if I can find multiple large (30+ person) Unity projects using it aggressively who all state that it actually - finally! - has been implemented to production level standard.

    SerializeReference is basically evil. It seems that almost nothing was learned from the 'we broke ScriptableObject, didn't test it enough, and some users spent a year losing their scene data every month (in some cases: weekly) while we flailed around' fiasco a few years ago.
     
    TextusGames and R1PFake like this.
  6. R1PFake

    R1PFake

    Joined:
    Aug 7, 2015
    Posts:
    542
    I don't have much experience with SerializeReferences, because after using them for a short time I already noticed issues, some where already posted in forums (like in this thread) and I also made a few bug reports.

    But I agree with the previous poster. I just can't trust the system in the current state and will not use it until Unity gives it more attention.

    Tbh can't even trust ScriptableObjects fully, that's why I only use them in "simple" cases, but that's a different topic.
     
  7. oscarAbraham

    oscarAbraham

    Joined:
    Jan 7, 2013
    Posts:
    431
    Yeah... before 2021.2, renaming is a big problem. Not only are references set to null: any changes made won't be saved. Also, sometimes references to Unity Objects with these problems become null after reimporting. However, I've found that once one gets used to fix these errors the moment they appear, things aren't too bad; no work is lost.

    That said, if you upgrade to 2021.2 or later, these problems will become a lot easier. 2021.3 has just become LTS, so I'd really recommend upgrading to it. SerializeReference is so much better in newer Unity versions. When a referenced class is missing, it's specially marked and set to null; your object still works and you can replace the reference with another class or just delete it directly. You can also do a lot more with them, like obtaining the reference object through SerializedProperty.managedReferenceValue, or manipulating the backing data system with SerializationUtility.

    Not only it's a lot less buggy; bugs that appear are generally a lot easier to go around because the API and the backing code is more robust. Also, the docs are a clearer and more complete.

    That said, if you want to rename a class and have it work immediately without doing anything with custom editor code, you still need to use a MovedFrom attribute. I don't think that will ever change because there's no other way for the engine to know that a class has been renamed, but it's sad that it's still not documented at all :(. Other than that, it's really a lot nicer :).
     
    Last edited: Apr 22, 2022
  8. a436t4ataf

    a436t4ataf

    Joined:
    May 19, 2013
    Posts:
    1,933
    That's great.

    But this feature appeared in 2019.x well before 2019 LTS if I remember correctly.

    Which means Unity has 2019 LTS, 2020 LTS, and the reaction to 'it corrupts your scene' is ... what?

    'meh; suck it up, buttercup'?
     
  9. oscarAbraham

    oscarAbraham

    Joined:
    Jan 7, 2013
    Posts:
    431
    On the renaming classes corrupting the scene before 2021.2, in case it helps, I've found it's a little complex, at least in my experience. Technically, it doesn't corrupt the scene; it freezes an Object in an attempt to prevent it from being corrupted (I know, ironic). Then, when one changes stuff in the editor, some of those changes aren't saved because some objects are frozen, which results in inconsistencies, lost work and possible corruption. It doesn't help that the error says nothing about it; it says what happened, but it doesn't mention the consequences.

    On the Unity bad thing... That time in Unity's history was a bit messy. Not just on this; there was a lot of messy stuff in those couple of years. It really seems to me like things are looking a lot better now. I think it's important to point out when tools aren't working, but when they get fixed we should let things be uplifting. I'd suggest that it's better to meet good stuff with encouragement than discouragement.

    I wish these things were handled better in 2019 and 2020, but hey, 2021.3 fixes a lot of this and is LTS now; the future is looking bright. For so long things like generics serialization or polymorphic serialization seemed like a really nice, impossible dream. I'm very happy they are a thing now. It's really world changing stuff; it feels like it deserved a bunch of blog posts and official forum threads. I'd like management at Unity to notice importance of this kind of development. I'd like to encourage more of it.
     
  10. yoonack

    yoonack

    Joined:
    Apr 29, 2016
    Posts:
    16
    I was having issues with 2020.3 for SerializedReference attribute. The performance is very bad with array in Reorderablist. It seems editor calls SerializedProperty.GetHashCodeWithoutArrayIndexPrpopertyPath that took up so much time on OnInspectorGUI if the SerializedReference array is inside another array element with large array index. However, after upgrading to 2021.3, the problem is gone. I am not sure if there is improvement to SerializedReference or just somehow Unity magically solve that.
     
  11. reuno

    reuno

    Joined:
    Sep 22, 2014
    Posts:
    4,929
    Hi there! I feel like I've read every possible thread on the subject, but still can't figure it out. It's pretty specific but maybe someone here will have an idea.

    Basically I've found out (the hard way) that moving classes used in a list with a SerializeReference attribute from one asmdef to another will break said lists on prefab instances.

    Here's how to reproduce the issue :

    - I have a monobehaviour, ThingContainer, that was under asmdef A
    - that mono contains a list of Things, with a SerializeReference attribute
    - for reasons, I wanted to move all my Things under a new asmdef, B
    - this broke the SerializeReference lists on all objects created before the change though, and it took me a while to discover the very undocumented MovedFrom attribute, and it's now ALMOST working
    - it works if in an old scene (created before the asmdef move) I had a regular ThingContainer, it works if I had ThingContainers in prefabs, without any override on the list
    - BUT it doesn't work for all instances of prefabs in my scenes where I had overrides on that list

    And indeed, if I check the scene in text mode, I can clearly see the list is referencing classes from the old asmdef, as if the MovedFrom attribute was ignored. Editing the scene in text mode to fix the strings fixes the issue of course, but that's not scalable. I've tried hooking myself to OnBeforeSerialize for example, but the list is seen as empty at that stage, so I have nothing to work on.

    I've reported the issue to Unity, but very open to suggestions in the meantime, as this is blocking for me.
     
    SonicBloomEric likes this.
  12. reuno

    reuno

    Joined:
    Sep 22, 2014
    Posts:
    4,929
    On a side note, I just found out about this, and it's gonna be a problem as well.
    upload_2022-5-27_16-30-24.png
     
  13. AndrewSkow

    AndrewSkow

    Unity Technologies

    Joined:
    Nov 17, 2020
    Posts:
    91
    Hi reuno

    Regarding "Editing the scene in text mode to fix the strings fixes the issue of course, but that's not scalable"
    Normally we caution about any sort of direct edits to YAML files, as it has to be done very carefully to make sure the edited file is still valid and parseable by Unity. But in the case of SerializeReference, i think that changes to a class names (assembly or namespace) can be performed relatively safely with batch "search and replace" actions in the YAML scene and asset files. The string format is relatively distinctive and is directly used to determine the target class when reloading. Of course be sure to back everything up prior to doing any direct edits.

    And regarding the warning message you saw "The list of [SerializeReference] objects being deserialized is from a more recent version of unity...." : In 2021 we moved to a new serialization format for the "references" section for SerializeReference objects. Unity can continue to load the old format. But 2020 and prior cannot read that newer format. So if you hit that error, it seems to mean that you had saved assets with the newer format with a newer version of Unity and are now trying to go backwards.

    More generally: I wanted to say that we've been putting a lot of attention to fixing SerializeReference issues in the past couple years, and the bug reports and improvement requests you have been logging are very important for us. At times the bug reports provide large projects with complex class hierarchies, so we have difficulty to narrow things down enough to conclusively find a root cause and generalize it to a fixable bug. We also spend a lot of time trying to categorize bug reports and accurately identify duplicates, but sometimes those pairings might turn out to be wrong, especially if it involves hard to reproduce crashes. But the effort to report bugs to us is much appreciated and I know often Unity users put a lot of work into preparing those repro steps and projects that are submitted. Some bug fixes can be backported, others depend on more significant changes in the software, so they cannot be reapplied in older branches. But rest assured that this area has been improving in quality and functionality, and it remains very much a goal to make sure SerializeReference works well as it gets more and more usage. Your help and feedback is much appreciated.
     
  14. reuno

    reuno

    Joined:
    Sep 22, 2014
    Posts:
    4,929
    @andrew_skowronski > I'm publishing assets on the store. I know how to / can make edits to YAML in my own projects, but can't do that in all my customer's projects. Right now the system prevents any sort of refactoring involving asmdefs and SerializeReference, which is pretty blocking for asset store publishers in particular, and to some lesser extent anyone dealing with both asmdefs and SR.

    And thanks for the explanation about the "more recent..." error!
     
    oscarAbraham likes this.
  15. oscarAbraham

    oscarAbraham

    Joined:
    Jan 7, 2013
    Posts:
    431
    Hi. Just found this bug, thanks for sharing. It's pretty ugly. I want to ask you a couple of questions if it's okay:
    - Are you seeing these three messages in the console for every affected prefab instance? I'm seeing them in 2021.3:
    Capture.PNG
    - Have you reported it? If so, has it been added to Unity's Issue Tracker?

    @andrew_skowronski In case it helps, at least in 2021.3, it seems to happen when these circumstances coincide:

    - It happens while data from a prefab asset is propagated to its prefab instances.
    - It only happens if the prefab instances have an overriden ManagedReference that uses a missing class name. To be clear, a whole reference must be defined in a prefab override, not just a field in a reference defined in the prefab asset. It looks something like this under m_Modifications inside the asset:
    Code (CSharp):
    1.     - target: {fileID: -3764041019655324203, guid: 7b3149446d8a83846ac46fa901bdbabe,
    2.         type: 3}
    3.       propertyPath: managedReferences[8735686136451825707]
    4.       value: Assembly-CSharp OldClassName
    5.       objectReference: {fileID: 0}
    This means that it happens when a class, namespace, or assembly is renamed with MovedFromAttribute, and that class is used in both prefab overrides and prefab assets. My guess is that it happens because the prefab asset propagates the new class type to the prefab instances. It also happens when reverting any single property in an affected prefab instance; that's why I think "it happens while data from a prefab asset is propagated to its prefab instances".

    The only way to stop these errors from happening in the Editor is to revert the whole component in each prefab instance. My guess is that only that way the override that references the missing class is deleted. (Side note: There's no other way of removing these overrides, as they don't belong to a SerializedProperty. It'd be nice if there was a way, because they can bloat a scene after a while.)

    Also, it is a lot uglier than just the references not working, at least in 2021.3. The prefab instance's deserialization process is interrupted, so all the fields that come after the error are set to their default value. This is terrible because it can cause lost work and data corruption. If you add to that that there's no obvious indication of that happening, so one could notice the effects a lot later, it compounds into a really awful potential for issues.
     
  16. reuno

    reuno

    Joined:
    Sep 22, 2014
    Posts:
    4,929
    @oscarAbraham > Yes, I get similar messages for every prefab instance.
    And yes, I've reported it (almost a month ago) but as usual, haven't heard back yet. Hopefully someday.
     
    oscarAbraham likes this.
  17. AndrewSkow

    AndrewSkow

    Unity Technologies

    Joined:
    Nov 17, 2020
    Posts:
    91
    Thanks @reuno for explaining why YAML updates are difficult, i see what you mean when you are publishing.

    I'm not familiar with the problem with prefabs + SerializeReference + MovedFrom that you and @oscarAbraham have reported, thanks for explaining it that sounds like enough info to investigate it. But do you have a link to the issue that you reported, I didn't find it in our bug tracking system.
     
  18. reuno

    reuno

    Joined:
    Sep 22, 2014
    Posts:
    4,929
    AndrewSkow likes this.
  19. AndrewSkow

    AndrewSkow

    Unity Technologies

    Joined:
    Nov 17, 2020
    Posts:
    91
    Thanks for the info @reuno. I've looked into that bug report, it was delayed because it does not have repro project with precise steps suitable for testing against multiple Unity versions. It just has the verbal description of the issue, so was difficult to verify by people less familiar with that feature. I think there is enough information for a developer to try to come up with a scenario to test and reproduce it, so we have taken it into our triage pile, but I wanted to explain why this particular report was not yet leading to any fast response.
     
    oscarAbraham and Qriva like this.
  20. reuno

    reuno

    Joined:
    Sep 22, 2014
    Posts:
    4,929
  21. SonicBloomEric

    SonicBloomEric

    Joined:
    Sep 11, 2014
    Posts:
    1,090
    TextusGames, Flavelius, Qriva and 3 others like this.
  22. reuno

    reuno

    Joined:
    Sep 22, 2014
    Posts:
    4,929
    SonicBloomEric likes this.
  23. chriscode

    chriscode

    Joined:
    Mar 2, 2015
    Posts:
    49
    Failing to get this to work! What's going on!?

    public interface MyInterface {}

    [Serializable]
    public class TestThing : MonoBehaviour {
    [SerializeReference]public MyInterface myinterf;
    }

    Just shows blank rectangle with name in inspector...
     
  24. vertxxyz

    vertxxyz

    Joined:
    Oct 29, 2014
    Posts:
    109
    That's what you get. Without a property drawer or editor there is no UI unless something has been assigned.
    I have one, but it may have issues under certain circumstances. I'm looking to update it to support UIToolkit, but facing many bugs in that direction that has directed my time elsewhere.
     
  25. Shrubokrant

    Shrubokrant

    Joined:
    Oct 2, 2016
    Posts:
    80
    Hi,
    Sorry to revive an old thread, but there is again a bug with SerializeReference and prefabs in 2022.2.1f
    EDIT: the bug may be coming from Odin Inspector, I'm not sure.
    EDIT2: Tested with and without Odin, the bug is definitely on Unity's side
    Consider the following scripts:

    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. namespace BFT
    4. {
    5.     public class RefTestComponent : MonoBehaviour
    6.     {
    7.         [SerializeReference]
    8.         public IRefTest RefTest;
    9.     }
    10. }
    Code (CSharp):
    1. namespace BFT
    2. {
    3.     public interface IRefTest
    4.     {
    5.      
    6.     }
    7. }
    Code (CSharp):
    1. namespace BFT
    2. {
    3.     public interface INestedRefTest
    4.     {
    5.      
    6.     }
    7. }
    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. namespace BFT
    4. {
    5.     public class NestedRefTestImplementation :INestedRefTest
    6.     {
    7.         public GameObject go;
    8.         [SerializeReference]
    9.         public INestedRefTest NestedRef;
    10.     }
    11. }
    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. namespace BFT
    4. {
    5.     public class RefTestImplementation :IRefTest
    6.     {
    7.         public GameObject go;
    8.         [SerializeReference]
    9.         public INestedRefTest NestedRef;
    10.     }
    11. }
    When putting the following script in a prefab, linking to its own gameobject, then when creating an instance of the prefab, only the first reference (the one in RefTestImplementation) points to itself in the instance, the rest of the fields are pointing to the prefab game object: upload_2023-1-10_0-34-3.png
    On the image, the blue one is correct, the red ones are wrong.

    Is that the intended way, or is that a bug?
     
    Last edited: Jan 10, 2023
    Catsoft-Studios likes this.
  26. oscarAbraham

    oscarAbraham

    Joined:
    Jan 7, 2013
    Posts:
    431
    If I understand correctly, that only the first reference gets replaced with a reference to the instantiated GameObject, I think it's a bug. I think it's worth reporting it. Also, there's a new thread for stuff related to SerializeReference here.

    A note: you may want to add the [System.Serializable] Attribute to your plain classes. It seems to work without it, but the documentation says it's needed.
     
  27. Shrubokrant

    Shrubokrant

    Joined:
    Oct 2, 2016
    Posts:
    80
    Good point! Seems like it works without, but yes it should be required.
    I reported the bug, but also will make a post over this thread, thanks for sharing!
     
    oscarAbraham and Catsoft-Studios like this.
  28. Catsoft-Studios

    Catsoft-Studios

    Joined:
    Jan 15, 2011
    Posts:
    703
    Could you post the bug ID or issue tracker link when it's validated by Unity? So we can track the progress. Thanks!
     
    Nivagia and oscarAbraham like this.
  29. Shrubokrant

    Shrubokrant

    Joined:
    Oct 2, 2016
    Posts:
    80
    Sure! No bug created yet unfortunately
     
    Nivagia and Catsoft-Studios like this.
  30. nickicool

    nickicool

    Joined:
    Jan 19, 2022
    Posts:
    11
    is it still not possible to set/select a GameObject in the inspector by interface?

    Code (CSharp):
    1.  
    2. public interface IDevice {}
    3.  
    4. [Serializable]
    5. public class Device : MonoBehaviour, IDevice {}
    6.  
    7. public class PlayerActor : MonoBehaviour
    8. {
    9. [SerializeReference] private IDevice device;
    10. }
    11.  
    No new fields appear in the inspector.
    Unity 2022.3.2f
     
    TextusGames likes this.