Search Unity

SerializeReference Attribute?

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

  1. elseforty

    elseforty

    Joined:
    Apr 3, 2018
    Posts:
    249
    kyuskoj likes this.
  2. kyuskoj

    kyuskoj

    Joined:
    Aug 28, 2013
    Posts:
    49
    Hi. I have 2 questions.

    1. Empty class(no field) instances in [SerializeReference] field are not deserialized and it becomes null when I back from prefab mode. Is this by design?

    I pushed a dummy data to make it work.
    Code (CSharp):
    1.  
    2. [Serializable] public class StartFsmCommand : ICommand
    3. {
    4.     [HideInInspector] public int dummy;
    5.  
    6.     public void Execute(object target) {};
    7.     public void Undo(object target) {};
    8. }

    2. [SerializeReference] attribute serializes a custom class which has no [Serializable] attribute. Is it intended?
     
    Last edited: Feb 7, 2020
    CyrilGhys and Hyp-X like this.
  3. LeonhardP

    LeonhardP

    Unity Technologies

    Joined:
    Jul 4, 2016
    Posts:
    2,837
  4. NWHCoding

    NWHCoding

    Joined:
    Jul 12, 2012
    Posts:
    1,350
    I am glad to see that 2019.3.1f1 fixed [SerializeReference] list using wrong PropertyDrawer for its elements.

    The issue that was introduced is:
    - Editor is extremely slow when drawing a ReorderableList that has [SerializeReference] attribute.
    - Game mode is not usable when ReorderableList above is visible in the inspector window.

    This was not an issue in 2019.3.0f6 and no code was changed in the meantime.
    Should I submit a bug report or is this a known issue?

    Also, here are deep profiler results (performance is bad when moving an element but also when doing nothing):
    upload_2020-2-13_11-41-21.png

    It seems that DoList() takes a lot of time.
    Here is what is being drawn:
    upload_2020-2-13_11-42-34.png

    And a video:


    Worked perfectly smoothly in previous version and the rest of the inspector works great - only the reorderable list causes massive slowdowns.

    EDIT: Even with one element in the list with a bool and float field it is still noticeably slow.

    EDIT2: Submitted this as a bug, case: 1219277

    EDIT3: Non-SerializeReference list performance is normal. <= Ignore that, it is also much slower than before and shows lag when more elements are added.
     
    Last edited: Feb 14, 2020
    TextusGames likes this.
  5. TextusGames

    TextusGames

    Joined:
    Dec 8, 2016
    Posts:
    420
    Prefab instance bug.

    Instances of prefab
    are not serializing the type of field with serialized reference attributes. (the field is not marked as an override)
    After entering play mode the field type reverts back to type that is assigned in the prefab.
    It does, however, serialize changes made inside child fields ( if field type of instance is the same as in prefab). ( But after change made and the field was marked as an override, It still is not saved and after entering playmode reverts back to prefab field type).

    Noticeably clicking apply all overrides applies overrides to prefab as expected.

    @LeonhardP Is this a known bug?

    Edited.
    It appears it is a known limitation.
    https://forum.unity.com/threads/can...ereference-fields-in-prefab-instances.776669/

    It is kind of a shame because you use polimorfism to override behaviours. And prefab instance can be overriden too, but they are sadly not compatible for now.

    Edited.
    I was hoping may be prefab variants can override type of serialized reference atribute. But it still resets back..
     
    Last edited: Feb 14, 2020
    kyuskoj, phobos2077 and NWHCoding like this.
  6. TextusGames

    TextusGames

    Joined:
    Dec 8, 2016
    Posts:
    420
    Nasty renaming bug...

    Renaming used child type will set all your fields of parent type with serialized reference to null. And console will be throwing errors like this " Unknown managed type referenced: [AmimalWorld].Bird ".

    Renaming child class back does not restores data. So renaming a child class that was used at least in one field will loose all your data even in fields there it was not used....

    How are we supposed to rename child types that are used in fields with [SerializeReference]?
    How do you plan to support child class renaming?

    @LeonhardP Is this a known bug?
     
    Last edited: Feb 14, 2020
  7. TextusGames

    TextusGames

    Joined:
    Dec 8, 2016
    Posts:
    420
    I have a very extreme slow down of inspector even if one field(with SerializeREference attribute) is presented in deeply nested class that is in arrays (and the array is not marked as a serialized reference just one field in youngest child class).
    It is so slow even for 10 elements, that the unfolding variable can take 5 seconds.
    In (2019.3.1f1).

    Edited.
    I can confirm that this is a regression in 2019.3.1.f1 from 2019.3.0.f6.
    In 2019.3.0.f6 inspector is not slow at all.
     
    Last edited: Feb 16, 2020
  8. NWHCoding

    NWHCoding

    Joined:
    Jul 12, 2012
    Posts:
    1,350
    ReorderableList for normal, non-SerializeReference lists, became extremely slow for me.

    The release of my asset hinges on this and Unity has been promising to fix SerializeReference for quite some time. I am starting to worry that they are out of their depth with SerializeReference in general - or at least out of testing personnel.
     
  9. TextusGames

    TextusGames

    Joined:
    Dec 8, 2016
    Posts:
    420
    Since the [SerializeRference] is far from production-ready we need a thread for feedback.
    2019.3 beta thread is in the archive and not immediately visible for new users.
    Can someone move this thread into 2020.1 alpha/beta (since it is not archived and visible)?
    And old and new users can continue to gather feedback on this exiting feature.

    @alex-abreu-unity @LeonhardP @karl_jones @jasonm_unity3d @superpig
     
  10. NWHCoding

    NWHCoding

    Joined:
    Jul 12, 2012
    Posts:
    1,350
    No fixes for ReorderableList OR SerializeReference in 2019.3.2f1. Anyone from Unity even attempting to fix this?
    I have an asset about two weeks from release and reworking it to not use [SerializeReference] seems to be the only option at the moment as I have lost faith in Unity team to actually implement something properly. Will 2019 LTS have the fix maybe?
     
    kyuskoj likes this.
  11. NWHCoding

    NWHCoding

    Joined:
    Jul 12, 2012
    Posts:
    1,350
    One more issue:
    When using [SerializeAttribute] list with public MonoBehavior (could also be other types, have not tested) field that has [NonSerializable] attribute, that field will get reset to initial value (null) each time a value in the inspector is changed.
    So if you set the value at Start() during play mode changing any other value in the inspector will reset the [NonSerializable] fields.

    Edit: All non-serialized fields will get reset as if Play() was just pressed each time any value in the inspector is changed. Only the public fields retain their values.
     
  12. NWHCoding

    NWHCoding

    Joined:
    Jul 12, 2012
    Posts:
    1,350
    I have compiled current list of issues with SerializeReference.

    Current issues:
    • Performance of lists (especially ReorderableList) since 2019.3.2f is awful. No such issue with version before.
    • Adding element to a SerializeReference list through editor to a prefab instance will not make it dirty and it is impossible to mark it dirty in any way.
    • [NonSerialized] and private fields will get reset to default value each time a field is modified inside the inspector for that object.
    • If using ReorderableList to draw the SerializeReference list when order of elements is changed message saying that "Undo.RegisterCompleteObjectUndo" is required (which I am using) and mentioning that the type tree has changed pop up. The issue that the message is generated from the internal code so no trace is available.
    • Dragging elements inside ReorderableList for [SerializeReference] List will improperly size the background Rect for the dragged object to the size of the current position in the list. Meaning that element 1 is 50 pixels high and element 2 is 300 pixels high, when swapping the position of those two element 1 will be 300 pixels high while being dragged over element 2's position and element 2 will be 50 pixels high.
     
  13. TextusGames

    TextusGames

    Joined:
    Dec 8, 2016
    Posts:
    420
    Also renaming issue.
    Renaming class that is used in field with serialized reference attribute will throw errors and set all fields of same type (even there it was not currently assigned) to null this will lead to loose of data.
     
    Last edited: Feb 23, 2020
    NWHCoding likes this.
  14. LeonhardP

    LeonhardP

    Unity Technologies

    Joined:
    Jul 4, 2016
    Posts:
    2,837
    Some updates on the issues:

    We have a fix for this issue in the pipeline. It's currently being reviewed so it will hopefully not be much longer.

    This is a known issue and the devs are working on it. No ETA for a fix at this point.

    This is a known issue and the team is working on a solution. I don't have an ETA for a fix here. The issue was previously discussed in this thread.

    The unknown issues:

    We didn't have a bug logged for this but I can see that you already submitted a report. Thanks for that! If it gets verified as a bug, it will show up on the issue tracker here.

    We have nothing logged for this issue AFAIK. It would great if you could submit a report for this as well, ideally with a minimal reproduction project.

    Same as the above. A bug report would be appreciated. Please share the issue IDs in this thread if you submit reports for these cases. That makes it easier to follow up on them.
     
    Last edited: Feb 26, 2020
    a436t4ataf and TextusGames like this.
  15. Trinary

    Trinary

    Joined:
    Jul 26, 2013
    Posts:
    378
    I recently attempted to use serialized reference on a project I'm developing. I've found that when you use the SerializeReference tag on a list of non-templated elements and that list is populated with derived elements which are templated then the editor crashes every time you inspect the list. This crash happens even if you use a custom inspector drawer which doesn't attempt to display the list of elements in any way.

    The same crash happened when I replaced the base class with an interface. There appears to be no way that I can use the SerializedRefrence tag on a list of non-templated base types and fill it with templated elements.
     
    Last edited: Feb 26, 2020
  16. SonicBloomEric

    SonicBloomEric

    Joined:
    Sep 11, 2014
    Posts:
    958
    To be clear, by "templated" do you mean C# generics?
     
  17. TextusGames

    TextusGames

    Joined:
    Dec 8, 2016
    Posts:
    420
    Regression is very severe. 50 elments of a collection with serialized reference make working with inspector impossible it freezes about 5 seconds on every action. (It can possibly be as slow with just 50 separate fields with serialized reference attributes.)
    What was not the case in 2019.3.0f6.
    It is clearly a regression that was introduced in 2019.3.1f1 and is really the one that comletely denies using this feature.

    Also i somehow can not open the link. (
    The page you were looking for doesn't exist.
    You may have mistyped the address or the page may have moved.)
     
  18. LeonhardP

    LeonhardP

    Unity Technologies

    Joined:
    Jul 4, 2016
    Posts:
    2,837
    The page doesn't exist because the issue hasn't been verified yet. As I said, the link will start to work if that happens.
     
    TextusGames likes this.
  19. Trinary

    Trinary

    Joined:
    Jul 26, 2013
    Posts:
    378
    Yes that's right. Thank you.
     
  20. SonicBloomEric

    SonicBloomEric

    Joined:
    Sep 11, 2014
    Posts:
    958
    According to @karl_jones:

    It looks like support may be coming later this year...
     
    karl_jones likes this.
  21. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    5,702
    Its in 2020.1 alpha now

    Scripting: The serializer can now serialize fields of generic types (e.g. MyClass<int> someField) directly; it is no longer necessary to derive a concrete subclass from a generic type in order to serialize it.

    Note: SerializeReference does not support generic serialization at the moment, you will still need to use concrete classes when using SerializeReference.
     
    Last edited: Mar 3, 2020
    a436t4ataf and SonicBloomEric like this.
  22. Trinary

    Trinary

    Joined:
    Jul 26, 2013
    Posts:
    378
    Hmm.. in that case perhaps it should throw an exception rather than crashing the editor.
     
  23. TextusGames

    TextusGames

    Joined:
    Dec 8, 2016
    Posts:
    420
    Is this a known issue that then you create one element in list with serialize reference attribute then increase number of elements. This elements will refer to the same object and if you change values of one element all of them will be changed.
    With is not expected, buggy behaviour.

    Is this a bug? I hope that is.
     
  24. jasonatkaruna

    jasonatkaruna

    Joined:
    Feb 26, 2019
    Posts:
    64
    The usual behavior of adding items to a list in the unity inspector is to duplicate the previous element. I'm betting the behavior is the same, and since the duplication is by reference and not by value, this is why they refer to the same object.
     
  25. TextusGames

    TextusGames

    Joined:
    Dec 8, 2016
    Posts:
    420
    Then you increase the number of elements of the list you do not want it to be duplicated by reference. But the thing you get is that you have a list of just one object that can be changed to just one field I guess, what is the purpose of the list in that case.
    I do not think that duplicating by reference in inspector is desirable.
     
    jasonatkaruna likes this.
  26. MadWatch

    MadWatch

    Joined:
    May 26, 2016
    Posts:
    97
    Same issue here (with Unity 2019.3.4f1). My code looks like this:

    Code (CSharp):
    1. public class Graph : Root, ISerializationCallbackReceiver
    2. {
    3.   [HideInInspector] [SerializeReference] private List<Node> mNodes;
    4.  
    5.   public void OnBeforeSerialize()
    6.   {
    7.     // ... some stuff here...
    8.   }
    9.  
    10.   public void OnAfterDeserialize()
    11.   {
    12.     // Here mNodes contains the correct number of elements but they are all null
    13.   }
    14. }
    When OnAfterDeserialize() is called the node list contains only null references. However the nodes are deserialized properly at a later point. Could this be a bug that OnAfterDeserialize() is called before deserializing the references?
     
  27. LeonhardP

    LeonhardP

    Unity Technologies

    Joined:
    Jul 4, 2016
    Posts:
    2,837
    This is a known issue: https://issuetracker.unity3d.com/product/unity/issues/guid/1216813/
    It's currently being investigated.
     
  28. Ghat-Smith

    Ghat-Smith

    Joined:
    Aug 16, 2016
    Posts:
    36
    I saw that problem too, and did a bug report two weeks ago. I got this answer in FogBugz :

    "We successfully reproduced this issue and have determined that it is by design. We have had similar case reports in the past and the developers have been asked about this problem, their response was that, although this behavior might be undesirable, there are times when it is."

    Like you, I can't find any case where this behaviour can be desirable by default... It can't be a good design, unless you give a way to chose if an element is a reference to another element or not, and especially give the possibility to chose which one.

    Also, I noticed that if your script have multiple lists of SerializeReference of the same type, when you add an element to a list, it's creating a reference to the first created (or first found ?) element of the same type, even if it's from another list. So you can end with multiple lists sharing one same object reference.
     
    TextusGames likes this.
  29. TextusGames

    TextusGames

    Joined:
    Dec 8, 2016
    Posts:
    420
    I am really pity about that poor designer who is working in such big company and designs such things. Then I increase the size of collection I want to increase the size of it no more than what. I do not want it to be magical copy by reference without any indication( especially than usual list are duplicated by value). It seems for me that they are just do not want to spend resources on changing collection size increase logic in inspector.
    For copy by reference there should be another menu command.
     
    kyuskoj likes this.
  30. jasonatkaruna

    jasonatkaruna

    Joined:
    Feb 26, 2019
    Posts:
    64
    I sympathize with you. I think in general, the
    [SerializeReference]
    attribute doesn't have a good default inspector drawer. Whenever I want to edit it, it's usually through code or my own, custom inspectors, similar to what you built with the
    [SerializeReferenceButton]
    attribute (which is pretty sweet btw).
     
    ihgyug, kyuskoj and TextusGames like this.
  31. Yandalf

    Yandalf

    Joined:
    Feb 11, 2014
    Posts:
    469
    Hey, so I recently came upon this and it's a very great and promising feature.
    I've implemented it in a dialogue system where steps can have requirements and results, which are defined like this:

    Code (CSharp):
    1.     [Serializable]
    2.     public abstract class EffectResult
    3.     {
    4.         public abstract void Execute();
    5.     }
    6.     public class EffectResult_Flag : EffectResult
    7.     {
    8.         public AssetReference Flag { get { return _flag; } }
    9.         public bool Value { get { return _value; } }
    10.         [SerializeField] private AssetReference _flag;
    11.         [SerializeField] private bool _value;
    12.  
    13.         public override void Execute()
    14.         {
    15.             GlobalFlags.Flags[Flag.Asset.name] = Value;
    16.         }
    17.     }
    18.  
    And then simply create a List<EffectResult> in a ScriptableObject and mark this as SerializeReference.
    This all seems to work fine in the Editor, after I wrote a custom property drawer for stuff like this I can properly instantiate and serialize elements into this list.
    However, when I then try to access that list in another object at runtime I get an empty list.
    Am I doing something wrong? The rest of the ScriptableObject containing this list loads in perfectly fine.
     
  32. Yandalf

    Yandalf

    Joined:
    Feb 11, 2014
    Posts:
    469
    Disregard this, I was being stupid and didn't rewrite my getter to return the correct list. Everything's fine, problem existed between keyboard and seat ;)
     
  33. EyeMD

    EyeMD

    Joined:
    Feb 28, 2015
    Posts:
    11
    I wrote a Dialogue system with branching/tree data structure - Characters have List<Conversation>, conversations are List<Statements or Questions> and Statement/Question inherit from base class of node. Also doing something similar with a Quest system.
    I'm using BinaryFormatter to save/load data - my main issue now is serializing all of this data.
    I'm looking into using ISerializationSurrogate as well as ISerializationCallBackReciever.
    Although relatively new to Serialization, I understand the [SerializeReference] attribute allows serialization of nulls, but more importantly to me, polymorphism and c# object references.
    I'm still researching the best way to go about this - any thoughts on how I can use [SerializeReference] to streamline serializing branching tree data structure in pseudocode? Thanks,
     
    Last edited: Mar 30, 2020
  34. Yandalf

    Yandalf

    Joined:
    Feb 11, 2014
    Posts:
    469
    I've recently overhauled my own Dialogue system to use this tech as well :)
    Perhaps I can provide some inspiration.
    My Dialogue class contains flat collections of DialogueStep and DialogueChoice classes, which reference each other through indexes (for now): so a DialogueStep (DS1) references 2 Choices (DC1 and DC2) which both have a reference to two new steps DS2 and DS3.
    With the SerializeReference attribute, I can replace those index references with Object References instead. As long as I keep the actual source objects within those flat collections (for editing safety, so breaking a connection between a step and a choice by nulling it won't actually delete the object).
    As an added bonus, I managed to use SerializeReference to save out a Polymorphic Requirement class allowing me to enable/disable Dialogue Choices based on the current game state (does the player possess an item? etc.)
     
  35. jasonatkaruna

    jasonatkaruna

    Joined:
    Feb 26, 2019
    Posts:
    64

    Keep in mind that the references are local to that UnityEngine.Object, so your tree can't be spread out across multiple MonoBehaviours or ScriptableObjects.

    The SerializeReference attribute doesn't have an in-editor drawer for instantiating new objects, but it will show you what's already there. You'll likely want to instantiate the tree and set it up with an editor script rather than through the inspector.

    If you want a tree like structure that isn't local to a UnityEngine.Object, you'll have to use ScriptableObjects. These still support polymorphism--they just have to derive from the same scriptableobject base class.
     
  36. Yandalf

    Yandalf

    Joined:
    Feb 11, 2014
    Posts:
    469
    Yeah, that's an important caveat there!
    Don't expect references to work across multiple UnityObjects (and if I'm understanding the documentation right it doesn't serialize UnityObjects either. Other classes are fine).

    I did write a property drawer myself to combat this problem, actually! If you have a variable that you want serialized this way I added a little attribute which gets drawn as a type dropdown on the inspector, and it instantiates a new object to be stored in that value when used.
    All the code for that can be found here with an example!

    Edit: I forgot the code I posted there did not include the attribute I mentioned. That was added later and has never been put online. It shouldn't be difficult to implement yourself though :)
     
    jasonatkaruna likes this.
  37. jasonatkaruna

    jasonatkaruna

    Joined:
    Feb 26, 2019
    Posts:
    64

    Haha I wrote my own too! https://upm-packages.dev/-/web/detail/com.jasonboukheir.unity-editor-extensions

    It's basically the same thing as yours but with an object picker type drawer instead of an enum dropdown.

    I really think Unity should implement their own since I know of at least 3 different solutions to the same problem.
     
    Yandalf likes this.
  38. EyeMD

    EyeMD

    Joined:
    Feb 28, 2015
    Posts:
    11
    Awesome, thank you so much, very helpful.

    Once again, still figuring out serialization, this is slightly removed from [SerializeReference] but - when a class loaded/deserialized, there is a new instance of that object with identical field members created right?

    Let's say I have a plain old c# class that is serializable. Its constructor calls when I create it. I then serialize it and save it to the hardrive. After I remove references to it, I can see that the original instances Destructor is called. Then, when I load and deserialize and return this new instance, I'm able to call methods on it and access its data - but its constructor is never called.

    Feel like I'm missing something here - when a class is deserialized a new instance (identical to what was originally serialized) is created, but why is the constructor not being called? Thanks again,
     
  39. EyeMD

    EyeMD

    Joined:
    Feb 28, 2015
    Posts:
    11
    Thinking about it more, it makes sense to me now - after the class is deserialized it is introduced back into the game. But its not created anew, so it makes sense that the constructor isn't being called. Save/load is working for my dialogue and quest progression, Thanks again
     
  40. Qriva

    Qriva

    Joined:
    Jun 30, 2019
    Posts:
    272
    Hello, I would like to ask if someone could confirm if this is bug and should it be reported or it's already known problem. Tested in Unity 2019.3.7f1.
    I found it when tried to delete list element in custom editor, here are reproduction steps:
    1. First error: Create game object and attach VarsDemo component from below
    2. When attached, there should be 3 elements in the list deriving from BaseVar
    3. Right click on "Int #1" and Delete Array Element (second one)
    4. There should be "Unsupported type Vector3f" error in console
    5. Second error: Undo delete action (ctrl + z) to get initial state
    6. This time remove first element "Vector #1"
    7. The same error should appear, but after Undo there will be second one:
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class VarsDemo : MonoBehaviour
    6. {
    7.     [SerializeReference]
    8.     public List<BaseVar> variables = new List<BaseVar>();
    9.  
    10.     void Reset()
    11.     {
    12.         Vector3Var var1 = new Vector3Var();
    13.         var1.key = "Vector #1";
    14.         var1.value = Vector3.up;
    15.         variables.Add(var1);
    16.  
    17.         IntVar var2 = new IntVar();
    18.         var2.key = "Int #1";
    19.         var2.value = 1;
    20.         variables.Add(var2);
    21.  
    22.         Vector3Var var3 = new Vector3Var();
    23.         var3.key = "Vector #2";
    24.         var3.value = Vector3.forward;
    25.         variables.Add(var3);
    26.     }
    27. }
    28.  
    29. [System.Serializable]
    30. public abstract class BaseVar{
    31.     public string key;
    32. }
    33.  
    34. [System.Serializable]
    35. public abstract class Var<T>: BaseVar{
    36.     public T value;
    37. }
    38.  
    39. [System.Serializable]
    40. public class IntVar: Var<int>{
    41. }
    42.  
    43. [System.Serializable]
    44. public class Vector3Var: Var<Vector3>{
    45. }
    46.  
    @LeonhardP
     
    Catsoft-Studios likes this.
  41. Rodolfo-Rubens

    Rodolfo-Rubens

    Joined:
    Nov 17, 2012
    Posts:
    1,168
    Just passing by to say thanks to the UT, this feature is amazing!
     
  42. SKArctop

    SKArctop

    Joined:
    Feb 12, 2018
    Posts:
    29
    I'm trying to verify, using a UnityEvent (of any type) inside a serialized reference is undefined correct? It looks like my UnityEvent field is not correctly serialized and is left null after an assembly reload.
     
  43. calpolican

    calpolican

    Joined:
    Feb 2, 2015
    Posts:
    375
    I want to report a pretty annoying bug when you use serializedReferences in a prefab.
    I noticed for a while that a prefab of mine had references that instead of referencing components in my prefab instance, were referencing components in the prefab root inside my asset folder.
    After some time I discover the cause of this. It was linked to the presence of a reference to a component that had inside a field marked as [SerializableReference]. In other words, I believe that if you have a component marked as such, the script will encounter this issue with all the other references, making all those references useless and even corrupting the prefab.
    To solve, you can mark the reference to the object as [System.NonSerialized], or remove the [SerializableReference] component, but it would be better if Unity solves the issue.
     
  44. realcosmik

    realcosmik

    Joined:
    Nov 27, 2018
    Posts:
    20
    I recently posted a bug and sent it to unity that caused and error and maybe it unable to save modified fields on prefabs that contain serialized references. the error only occurred when trying to add modified components from the component context menu. The work around i found was to save changes from the overrides menu at the topic of the inspector. the error states
    "Could not update a managed instance value at property path
    UnityEditor.GenericMenu:CatchMenu(Object, String[], Int3)"
    i made a bug here https://issuetracker.unity3d.com/is...fields-that-have-serializereference-attribute
     
    Benzor likes this.
  45. Idodi1337

    Idodi1337

    Joined:
    Jul 7, 2014
    Posts:
    11
    Hi,

    I have a simple use case that I'm trying to implement, but I seem to only get an empty label when using SerializeReference. Using Unity version 2019.3.10f1

    Is the following use case not supported?

    Code (CSharp):
    1. public interface IStrategy
    2. {
    3.     void DoSomething();
    4. }
    Code (CSharp):
    1. using UnityEngine;
    2. public class ConcreteStrategy : IStrategy
    3. {
    4.     public void DoSomething()
    5.     {
    6.         Debug.Log("doing something");
    7.     }
    8. }
    Code (CSharp):
    1. using UnityEngine;
    2. public class Context : MonoBehaviour
    3. {
    4.     [SerializeReference] private IStrategy _strategy;
    5.  
    6.     private void Start()
    7.     {
    8.         _strategy.DoSomething();
    9.     }
    10. }
    When adding the Context mono behaviour to a game object the _strategy variable appears as an empty label ("Strategy") without having the chance to pass in a reference (which would be ConcreteStrategy, an IStrategy implementation).

    context.png

    Thanks
     
    Last edited: Apr 27, 2020
  46. Yandalf

    Yandalf

    Joined:
    Feb 11, 2014
    Posts:
    469
    That's because your IStrategy variable isn't initialized, therefore it is a null value which does not get drawn beyond the label in the inspector. If you were to initialize your value on declaration to a type that can be drawn by the unity inspector, that should work.
    People in this thread, myself included, have been writing their own inspectors. You might have to implement your own, so take a look around and get some ideas.
     
  47. Idodi1337

    Idodi1337

    Joined:
    Jul 7, 2014
    Posts:
    11
    I believe having to write and maintain an inspector for such a simple feature kind of defeats the purpose, doesn't it?
     
  48. Yandalf

    Yandalf

    Joined:
    Feb 11, 2014
    Posts:
    469
    That's why people like I are sharing their solutions.
    Also to be honest when you get a little acquainted with editor scripting and know your use cases for this tool, it really isn't that much of a problem to write an inspector.
    Do keep in mind it's still a preview feature, I'm pretty sure Unity will eventually make their own drawers for this system, though the problem is a little complex.
    In the case of your IStrategy interface: what is the object sticking in that variable even supposed to be? If it's a Monobehaviour you probably want an object reference drawer in there, but what if you don't want an MB? Since it's such an open problem I don't expect any Unity solution to "just fit" for everyone without some configuration from the users, probably some attributes to indicate what kind of drawer you want...
     
  49. Idodi1337

    Idodi1337

    Joined:
    Jul 7, 2014
    Posts:
    11
    The reference would just be any script implementing the interface such as ConcreteStrategy (code supplied above)
     
  50. Yandalf

    Yandalf

    Joined:
    Feb 11, 2014
    Posts:
    469
    Yeah, but your declaration doesn't say that. That's the problem.
    Your inspector drawer just sees an interface, which is an abstract element with no more information, so it skips drawing them since there's no way for it to know for sure what's in there, or what you even really want.
    That's why you need to do some thinking how you're going to use this attribute, and (for now) build your own drawers for it to fit your use case.

    In my case for example I wanted arrays of abstract elements that I could set up in the inspector with many different subclasses, so my drawer simply adds a little dropdown to the inspector where you can specify which subclass you want each element to be, after which the element gets constructed and the regular inspector drawers take over. Code's over here.
     
unityunity