Search Unity

  1. Unity 2019.2 is now released.
    Dismiss Notice

SerializeReference Attribute?

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

  1. Peter77

    Peter77

    Joined:
    Jun 12, 2013
    Posts:
    4,210
    Can you please post the bug-report case number (number only, not the link) here for Unity staff to pick up.
     
  2. mykillk

    mykillk

    Joined:
    Feb 13, 2017
    Posts:
    59
    Not sure what's going. Haven't received a followup email with my case number and I see on the Unity issue tracker that the last issue added was over a week ago!
     
  3. LeonhardP

    LeonhardP

    Unity Technologies

    Joined:
    Jul 4, 2016
    Posts:
    1,654
    The Issue Tracker wasn't updating since September 29th which has now been fixed. Regarding the missing confirmation emails, that issue is still being investigated.
     
    Peter77 likes this.
  4. Roni92pl

    Roni92pl

    Joined:
    Jun 2, 2015
    Posts:
    286
    Does that mean inspector will be able to finally display interfaces fields?
     
  5. mykillk

    mykillk

    Joined:
    Feb 13, 2017
    Posts:
    59
    Were submitted bugs still being received and reviewed? Or do I have to report this bug yet again?
     
  6. AlkisFortuneFish

    AlkisFortuneFish

    Joined:
    Apr 26, 2013
    Posts:
    690
    Check your bug feed by looking at the fogbugz link for any other bug you have submitted. If it shows on the bottom left, yes, otherwise it has not been received.
     
    Last edited: Oct 10, 2019
    LeonhardP likes this.
  7. AlkisFortuneFish

    AlkisFortuneFish

    Joined:
    Apr 26, 2013
    Posts:
    690
    Yes, provided you use [SerializeReference] on the field.
     
  8. bsymon

    bsymon

    Joined:
    Dec 11, 2016
    Posts:
    11
    Hi !

    I was playing around with this new feature, but I may have an issue. I tried to "SerializedReference" a System.Object, but it doesn't work.

    I'm on the latest beta 2019.3.0b6.

    Here is my code, really simple :

    Code (CSharp):
    1. [SerializeReference]
    2. private object valueTest = default;
    I was expecting to something to show up in the Inspector, just the name of the property, but nothing's here ... I tried a custom editor, and grab a SerializedProperty of the field, but it returns null.

    Is it an expected behaviour, like System.Object can't be serialized ??
     
  9. tsukimi

    tsukimi

    Joined:
    Dec 10, 2014
    Posts:
    1
    Hello!

    The new attribute is really exciting, and I'm trying to work on this new fantastic serializing feature.

    It says that you can have null value for Serialized Reference Field, but when I do:
    Code (CSharp):
    1.  public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) {
    2.     if(some condition property should be reset to null...)
    3.         property.managedReferenceValue = null;
    4. }
    in a custom PropertyDrawer, it comes up with an error of NullRefectenceException:
    Code (Boo):
    1. NullReferenceException: Object reference not set to an instance of an object
    2. UnityEditor.SerializedProperty.set_managedReferenceValue (System.Object value)
    Is this an expected behaviour ,or should I report as a bug?
     
  10. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    3,551
    Hi. Thanks for trying the feature, this is a known bug, it should work in the future.
     
    Catsoft-Studios, Prodigga and tsukimi like this.
  11. Ben-BearFish

    Ben-BearFish

    Joined:
    Sep 6, 2011
    Posts:
    1,182
    Don't suppose SerializedReference will be back-ported to 2019.2?
     
  12. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    3,551
    No sorry, we avoid backporting features.
    This feature is also still being stabilised.
     
  13. Bastienre4

    Bastienre4

    Joined:
    Jul 8, 2014
    Posts:
    60
    Hello. I'm trying to use the [SerializeReference] attributes in my project. Unfortunatly, it makes the editor crash when I use the inspector to change a non serialize reference field like material reference or a enum field.
    The editor log doesn't say Unity crashed.
    I have reported a bug (1194244).
    Do you have any idea what could happen?
    Thanks and have a nice day
     
    artemio_morales likes this.
  14. AlkisFortuneFish

    AlkisFortuneFish

    Joined:
    Apr 26, 2013
    Posts:
    690
    Well, an editor crash is never treated as an acceptable bug, so it’ll be fixed is what will happen! ;-)
     
  15. Bastienre4

    Bastienre4

    Joined:
    Jul 8, 2014
    Posts:
    60
    Haha.
    I meant, do you have an idea what causes the crash and is there a workaround? :D
     
  16. Lelepoop

    Lelepoop

    Joined:
    Nov 14, 2016
    Posts:
    99
    Some type tree corruption related bug here: 1194488
    This seems to only happen if the serialized field is inside a class that doesnt inherit from MB or SO.
    There was also another crash that only occurs in a build relating to SerializeReference attribute and collections, does anyone else experience this?

    Hey @tsukimi if youre trying to change the object in the inspector, for now you can do so by setting the field directly (by using propertyPath and serializedObject.targetObject) and then dirtying the object.
     
  17. Log_N

    Log_N

    Joined:
    Jun 17, 2015
    Posts:
    7
    I've also experienced crashed and freezes (issue submitted) while trying to use [SerializeReference], but it is not always has same crash callback. Basically I have SO object with some data and [SerializeReference] array of custom classes. When I change any string in my SO object it does:
    - in most cases corrupt all data inside [SerializeReference] array instances;
    - if there is reference field in my custom class, it would result in crash (particularly if it is string and editor would try to present corrupted reference).
    Sometimes I see m_ByteOffset something-something error messages briefly before crash, which somewhat confirms that it is likely an issue with memory layout on native side.

    Code (CSharp):
    1. [........Utility/SerializedProperty.cpp line 1578]
    2. Assertion failed on expression: 'm_ByteOffset + m_TypeTreeIterator->m_ByteSize <= m_Data->size()'
    This feature is frankly unusable as it is done now, shame unity does not provide source code as UE does, so it would be possible to try to fix it myself.
     
  18. AlkisFortuneFish

    AlkisFortuneFish

    Joined:
    Apr 26, 2013
    Posts:
    690
    Do remember that this is a beta and the whole point of it is to fix those issues. Pretty sure both of those are related to a bug I reported, and that was already marked as a dupe and is being worked on.
     
    SonicBloomEric and karl_jones like this.
  19. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    3,551
    This is a known issue which we already have a fix for. It should be out soon.
     
    Log_N and SonicBloomEric like this.
  20. Log_N

    Log_N

    Joined:
    Jun 17, 2015
    Posts:
    7
    Yeah I get that. We may have different expectations of Beta stability, I would expect that feature in Beta branch (in contrast to Alpha) would be tested against normal usage. I do not mean to be negative though - it is a lesson.

    I'm happy to hear that fix would be out soon. It is an extremely useful feature that I'm very much looking forward to using, especially with support for the generics.
     
  21. toomasio

    toomasio

    Joined:
    Nov 19, 2013
    Posts:
    18
    I just wanted to thank you guys for implementing this. Seeing this work brought me tears of joy.
    Making custom editors is going to be 5x easier now.

    I made a little test if anyone wants to see how revolutionary this is for building Unity editors.

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using System.Linq;
    5. #if UNITY_EDITOR
    6. using UnityEditor;
    7. #endif
    8.  
    9.  
    10. public interface IFruit
    11. {
    12. }
    13.  
    14. public abstract class Fruit : IFruit
    15. {
    16.     public string fruitName;
    17. }
    18.  
    19. [System.Serializable]
    20. public class Apple : Fruit
    21. {
    22.     public enum AppleType { Gala, GrannySmith, RedDelicious }
    23.     [SerializeField] private AppleType appleType = default;
    24. }
    25.  
    26. [System.Serializable]
    27. public class Orange : Fruit
    28. {
    29.     public enum OrangeType { Valencia, Blood, Jaffa }
    30.     [SerializeField] private OrangeType orangeType = default;
    31. }
    32.  
    33. public class InspectorTesting : MonoBehaviour
    34. {
    35.     [SerializeReference] public List<IFruit> fruits = new List<IFruit>();
    36. }
    37.  
    38. #if UNITY_EDITOR
    39.  
    40. [CustomEditor(typeof(InspectorTesting))]
    41. public class InspectorTestingEditor : Editor
    42. {
    43.     private InspectorTesting source;
    44.     private SerializedObject sourceRef;
    45.     private SerializedProperty fruits;
    46.  
    47.     private int dropDownSelection;
    48.     private System.Type[] types;
    49.     private string[] names;
    50.  
    51.     private void OnEnable()
    52.     {
    53.         source = (InspectorTesting)target;
    54.         sourceRef = serializedObject;
    55.  
    56.         GetProperties();
    57.     }
    58.  
    59.     void GetProperties()
    60.     {
    61.         types = GetAllOfInterface(typeof(Fruit));
    62.         names = new string[1];
    63.         names[0] = "Add A Fruit!";
    64.         names = names.Concat(GetAllOfInterfaceNames(typeof(Fruit))).ToArray();
    65.         fruits = sourceRef.FindProperty("fruits");
    66.     }
    67.  
    68.     public override void OnInspectorGUI()
    69.     {
    70.         DisplayProperties();
    71.         sourceRef.ApplyModifiedProperties();
    72.     }
    73.  
    74.     void DisplayProperties()
    75.     {
    76.         dropDownSelection = EditorGUILayout.Popup(dropDownSelection, names);
    77.         if (dropDownSelection != 0)
    78.         {
    79.             var fruit = System.Activator.CreateInstance(types[dropDownSelection - 1]) as Fruit;
    80.             fruit.fruitName = fruit.GetType().Name;
    81.             source.fruits.Add(fruit);
    82.             dropDownSelection = 0;
    83.         }
    84.  
    85.         EditorGUILayout.PropertyField(fruits, true);
    86.     }
    87.  
    88.     string[] GetAllOfInterfaceNames(System.Type _interfaceType)
    89.     {
    90.         return GetAllOfInterface(_interfaceType)
    91.             .Select(x => x.Name)
    92.             .ToArray();
    93.     }
    94.  
    95.     System.Type[] GetAllOfInterface(System.Type _interfaceType)
    96.     {
    97.         return System.AppDomain.CurrentDomain.GetAssemblies()
    98.             .SelectMany(s => s.GetTypes())
    99.             .Where(x => _interfaceType.IsAssignableFrom(x) && x != _interfaceType && !x.IsAbstract)
    100.             .OrderBy(x => x.Name)
    101.             .ToArray();
    102.     }
    103.  
    104. }
    105.  
    106. #endif


    Any chance popup menus for enums will be implemented as default in the future?
     
  22. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    3,551
    Its a known bug, we should have a fix for it in the future.

    Glad you are enjoying the feature :)
     
    toomasio likes this.
  23. heiko-achilles

    heiko-achilles

    Joined:
    Nov 11, 2016
    Posts:
    1
    Hi.

    How is it supposed to work in an Editor class?
    SerializedProperty.managedReferenceValue is write-only, so how is the serialized class instance accessible from within an Editor class?
     
  24. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    3,551
    Yes, the SerializedProperty is lacking some API when dealing with managed references at the moment.
    You can still get to the properties via normal serialized Properties, you can not get the actual instance via a SerializeProperty which makes it very hard to actually share references in a generic way with an editor. We are working on improving this.
     
  25. mykillk

    mykillk

    Joined:
    Feb 13, 2017
    Posts:
    59
    An update on this. It looks like my bug report did in fact make it through to the engineering team. They just got back to me that this is expected behavior. Unity's serialization system does not support self-referencing class fields. The recommended workaround is to use an Interface instead, the same as what I demonstrated.

     
    Lelepoop and karl_jones like this.
  26. SonicBloomEric

    SonicBloomEric

    Joined:
    Sep 11, 2014
    Posts:
    640
    @karl_jones If it's not already, this is one of those gory details that should definitely be documented...
     
    Ludiq and karl_jones like this.
  27. AlkisFortuneFish

    AlkisFortuneFish

    Joined:
    Apr 26, 2013
    Posts:
    690
    I wonder why. It makes sense without SerializeReference, as it would cause infinite serialization depth without null support, but surely this stops any sort of linked list from being serialized?

    Edit: is the root of this serialized by reference itself? I’m not at work to test this, but I would expect it not to work if the root is not.
     
  28. Lelepoop

    Lelepoop

    Joined:
    Nov 14, 2016
    Posts:
    99
    @karl_jones are you able to confirm that the type tree related issues are linked to the sharedassets file being corrupted in builds and causing a crash on launch? Thanks to you and the team for this work btw, cheers.
     
  29. mykillk

    mykillk

    Joined:
    Feb 13, 2017
    Posts:
    59
    My guess is that there's probably still a lot of shared code path between SerializeField and SerializeReference. But I agree, it should be possible to have self-referencing class fields when using SerializeReference as it circumvents the issue at hand (infinite serialization depth) entirely. Perhaps that is something that can be changed eventually in a later release of Unity?
     
  30. Ludiq

    Ludiq

    Joined:
    Mar 6, 2015
    Posts:
    611
    Another neat perk of [SerializeReference] I just discovered is that it isn't constrained to the arbitrary maximum serialization depth of 7. Which may seem obvious considering it can be self-referencing, but it's also great for those complex nested type structures *without* self-referencing that you couldn't even serialize before because they went too deep.

    For example, this code used to fail to serialize Layer8.tooDeep and show :

    Screen Shot 2019-11-12 at 12.02.18 AM.png

    Code (CSharp):
    1. using UnityEngine;
    2. using System;
    3.  
    4. public class Depth : MonoBehaviour
    5. {
    6.     [SerializeField]
    7.     public Layer0 layer0 = new Layer0();
    8. }
    9.  
    10. [Serializable]
    11. public sealed class Layer0
    12. {
    13.     [SerializeField]
    14.     public Layer1 layer1 = new Layer1();
    15. }
    16.  
    17. [Serializable]
    18. public sealed class Layer1
    19. {
    20.     [SerializeField]
    21.     public Layer2 layer2 = new Layer2();
    22. }
    23.  
    24. [Serializable]
    25. public sealed class Layer2
    26. {
    27.     [SerializeField]
    28.     public Layer3 layer3 = new Layer3();
    29. }
    30.  
    31. [Serializable]
    32. public sealed class Layer3
    33. {
    34.     [SerializeField]
    35.     public Layer4 layer4 = new Layer4();
    36. }
    37.  
    38. [Serializable]
    39. public sealed class Layer4
    40. {
    41.     [SerializeField]
    42.     public Layer5 layer5 = new Layer5();
    43. }
    44.  
    45. [Serializable]
    46. public sealed class Layer5
    47. {
    48.     [SerializeField]
    49.     public Layer6 layer6 = new Layer6();
    50. }
    51.  
    52. [Serializable]
    53. public sealed class Layer6
    54. {
    55.     [SerializeField]
    56.     public Layer7 layer7 = new Layer7();
    57. }
    58.  
    59. [Serializable]
    60. public sealed class Layer7
    61. {
    62.     [SerializeField]
    63.     public Layer8 layer8 = new Layer8();
    64.  
    65.     [SerializeField]
    66.     public string stillGood = "Yay";
    67. }
    68.  
    69. [Serializable]
    70. public sealed class Layer8
    71. {
    72.     [SerializeField]
    73.     public string tooDeep = "oh no";
    74. }
    But if you replace any of the [SerializeField] by [SerializeReference] in that chain, then you can get tooDeep to show up and serialize:

    Screen Shot 2019-11-12 at 12.03.36 AM.png

    Now if only this crash could get fixed I'd start using it everywhere!
     
  31. Catsoft-Studios

    Catsoft-Studios

    Joined:
    Jan 15, 2011
    Posts:
    549
    This is amazing. I've been playing around with polymorphic data serialization and it works like charm. Huge thanks to the whole team.

    One question though, and pardon if I say something stupid, but i just want to clear any confusion. So the thing is that to set an integer variable from a
    SerializedProperty
    all you have to do is use the
    intValue
    . Same if you want to set a string, but using the
    stringValue
    . If you want to set an object that inherits from
    UnityEngine.Object
    (ScriptableObjects, MonoBehaviors or any Unity Component) you use
    objectReferenceValue
    .

    Up until now all clear. However, if you want to set a new instance of MyCat from a SerializedProperty, you have to use
    managedReferenceValue
    ? Doesn't "managed reference" mean there's a C++ counterpart object? Shouldn't it be named something like
    genericReferenceValue
    ?

    Code (CSharp):
    1. [Serializable]
    2. public class MyCat : Animal
    3. {
    4.     public int lifes = 9;
    5. }
     
  32. AlkisFortuneFish

    AlkisFortuneFish

    Joined:
    Apr 26, 2013
    Posts:
    690
    No, rather the opposite. Managed means it's in .Net/Mono/C# land.
     
    karl_jones and Catsoft-Studios like this.
  33. Catsoft-Studios

    Catsoft-Studios

    Joined:
    Jan 15, 2011
    Posts:
    549
    Thanks! I got this the other way around then