Search Unity

  1. The 2021.2 beta is now available. To find out what's new, have a look at our 2021.2 beta blog post.
    Dismiss Notice
  2. All Pro and Enterprise subscribers: find helpful & inspiring creative, tech, and business know-how in the new Unity Success Hub. Sign in to stay up to date.
    Dismiss Notice
  3. Dismiss Notice

SerializeReference Attribute?

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

  1. jerome-lacoste

    jerome-lacoste

    Joined:
    Jan 7, 2012
    Posts:
    185
  2. Elringus

    Elringus

    Joined:
    Oct 3, 2012
    Posts:
    399
    The issue with non-serialized Initialized fields lose their values was initially planned for 2019.3:


    But today it's changed to 2020.1 and later only:

    I was really hoping it will be fixed in a 2019.4 LTS release; is this not the case anymore? @LeonhardP @karl_jones

    The issue was also removed from the known issues in the 2019.3 changelogs. Has it magically become not an issue in 2019.3? :)
     
    Peter77, a436t4ataf and Jes28 like this.
  3. unity_Etienne

    unity_Etienne

    Unity Technologies

    Joined:
    Nov 28, 2019
    Posts:
    2
    Hi!
    Don't worry, this backport is still very much planned! It's just that it has been 'upgraded ' to 2019.4 but didn't get a new flag and lost the 2019.3 one.
    Thanks keeping track!
     
    Elringus likes this.
  4. NWHCoding

    NWHCoding

    Joined:
    Jul 12, 2012
    Posts:
    1,289
    Any updates on this? It has been over 5 months from the date I first reported the bug. Also, are there any other known SerializeReference issues or is it now finally production ready?
     
  5. alex-abreu-unity

    alex-abreu-unity

    Unity Technologies

    Joined:
    Jan 18, 2018
    Posts:
    6
    Hi,
    we are in the process of validating the fix and landing the bug fix, I will keep you posted here,
     
    kvfreedom and Jes28 like this.
  6. Qriva

    Qriva

    Joined:
    Jun 30, 2019
    Posts:
    119
    Last edited: Jun 16, 2020
  7. goodtime

    goodtime

    Joined:
    Nov 8, 2012
    Posts:
    55
    Hello.
    Is it possible to read and write SerializeReference with JsonUtility?
    I use Json Utility to read and write save data.
    I then used SerializeReference with JsonUtility, in Unity2019.4.
    It's working.
    However, it seems unstable.
    I use it during playing game, not in the editor.
    Is this a permitted use?
    If so, I will report the problem you are having as a bug report.
     
  8. marcpeyre

    marcpeyre

    Joined:
    Jan 23, 2014
    Posts:
    15
    I'm getting the following error message when I try to clear an array of structs containing a field with [SerializeReference]. Everything seems to work fine though, I can't find any side effects from the error. There is no callstack but I suspect it happens within serializedObject.ApplyModifiedProperties().

    "Could not reach source property name 'bindings.Array.data[0]' while extracting diffs, the reference does not exist in the source serialized data"

    Doing something like this gives the error:
    Code (CSharp):
    1. var _bindings = _variables.FindPropertyRelative( "bindings" );
    2. _bindings.ClearArray();
    3. serializedObject.ApplyModifiedProperties();
    Inserting an element right after prevents the error from popping up.
    Code (CSharp):
    1. var _bindings = _variables.FindPropertyRelative( "bindings" );
    2. _bindings.ClearArray();
    3. _bindings.InsertArrayElementAtIndex( 0 );
    4. serializedObject.ApplyModifiedProperties();
    Any ideas why this happens or how bad the error is?
     
  9. WAYN_Games

    WAYN_Games

    Joined:
    Mar 16, 2019
    Posts:
    657
    Hi @LeonhardP,

    Any update regarding the renaming of serialized reference items issue ?

    The issue tracker does not seem to know the issue number.
    I posted a comment in the referenced thread as well a few days ago but did not get any news.

    I have the same issue in my project. I made a custom inspector to manage a list of struct implementing an interface in a scriptable object and when renaming one of the reference struct, Unity seems to be unable to deserialze any element of the refrenced list, messing up the display for all element even the non renamed ones.

    For know I just detect the deserialization error and display a message but I would be great for it to handle the renaming, or at least not mess up de deserialization of the non renamed structs.

    Fixing the name in the .asset of the scriptable object fixes the deserialization issue but that's gonna be tidious with a big project...

    PS : I'm using 2019.0.f4f1
    Also affect 2020.1.0b12
    And 2020.2.0a15 seems even more broken
     
    Last edited: Jun 19, 2020
    kvfreedom likes this.
  10. Elringus

    Elringus

    Joined:
    Oct 3, 2012
    Posts:
    399
    phobos2077 likes this.
  11. MartinBarrette

    MartinBarrette

    Unity Technologies

    Joined:
    Oct 22, 2019
    Posts:
    24
    Hi Elringus,
    Unfortunately the original fix had side issues with array manipulation(re-ordering/deleting elements, could cause crashes and invalid data presentation in some cases). We are currently working on a fix which will keep the original benefits while addressing the current issues with array manipulation.
    https://issuetracker.unity3d.com/is...in-the-custompassvolume-preset-from-inspector

    The aim is to backport it once we have addressed those cases.
    Hope this helps.
    Martin
     
  12. SonicBloomEric

    SonicBloomEric

    Joined:
    Sep 11, 2014
    Posts:
    917
    Would it not make sense to update Issue 1193322 with this information and adjust the state of it accordingly?

    Right now the bug status is a lie.
     
  13. Elringus

    Elringus

    Joined:
    Oct 3, 2012
    Posts:
    399
    Thank you for the clarification!

    I guess it's not technically a lie, as 1193322 fix was implemented in 2020.2 (and is still there), which then caused 1260516, so the review process for the backports is on hold (to prevent breaking stuff for the 2019.4 and 2020.1 users). Additional comment on 1193322 with a link to 1260516 would be helpful, though.
     
  14. SonicBloomEric

    SonicBloomEric

    Joined:
    Sep 11, 2014
    Posts:
    917
    A fix is no longer "currently in review". It failed the review. It should be updated to point to the new issue.
     
  15. MartinBarrette

    MartinBarrette

    Unity Technologies

    Joined:
    Oct 22, 2019
    Posts:
    24
    Hi,
    Issue 1193322 status has been updated with an explanatory note.
    Cheers
     
  16. TextusGames

    TextusGames

    Joined:
    Dec 8, 2016
    Posts:
    415
    Did anyone try to create a build that has scriptable object with serialize reference field of class that also has a different field with serialize reference attribute. It works in editor but in runtime build it creates "serialization mismatch exeption" and all data become null. Can it be related to above issue or is this a separate bug?
     
  17. MartinBarrette

    MartinBarrette

    Unity Technologies

    Joined:
    Oct 22, 2019
    Posts:
    24
    It is not linked to the above issue. What is your "Managed Stripping Level" for your player build? There is currently a known issue https://issuetracker.unity3d.com/is...es-used-with-the-serializereference-attribute
    which is more likely to be the culprit. If this is the case you can workaround the issue using [UnityEngine.Scripting.Preserve] https://docs.unity3d.com/ScriptReference/Scripting.PreserveAttribute.html.
    Hope this helps.
     
  18. TextusGames

    TextusGames

    Joined:
    Dec 8, 2016
    Posts:
    415
    Wow, thank you, Martin. It is quite possible. I will test without striping and with stripping and [Preserve] attribute.
     
  19. a436t4ataf

    a436t4ataf

    Joined:
    May 19, 2013
    Posts:
    1,256
    How do we find a list of what parts of SerializeReference are broken/fixed in a specific Unity version - at the very least: how much of it actually works in LTS (2019.4) and how much actually works in the non-LTS (2020.1)?

    The "August 2020" version of this appears to be:

    Still broken in 2019.4:
    Still broken in 2020.1:
    (There's lots of good fixes in this thread, but ... without a list where we can see what's "known broken" it's pretty much useless: we can't assess/evaluate whether it's useable yet for our own cases)

    PS: I opened every IssueTracker that was shared in the thread. Obviously, because Unity doesn't make Case numbers public, I had to ignore all Case numbers and hope that the unfixed ones people had also posted the IssueTracker links eventually. Would be nice if one day Unity would make bug reports public :)
     
    Last edited: Aug 3, 2020
    Jes28 and TextusGames like this.
  20. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    5,052
    What do you mean? The issue tracker is public bug reports. When a bug is processed and the submitter sets the public flag then it appears on the issue tracker. We don't put them up before hand because it would fill the issue tracker with spam and invalid bug reports.
     
  21. a436t4ataf

    a436t4ataf

    Joined:
    May 19, 2013
    Posts:
    1,256
    I don't want to derail the thread, but ... as far as I'm aware, the Issue Tracker is:

    1. Not trackable from a Case number (which is the only thing submitters are given). So every time I log a bug: the community gets no beneift, only Unity internal staff have the power to see the bug (even after an Issue Tracker was made for it). Unless every poster volutntarily returns to every old forum post every time they receive an IssueTrcker link and edit it back-in (which - e.g. for Unity XR is currently about FOUR MONTHS after the bug was submitted: there's no way I can even remember where and whether I shared that bug originally).
    2. Missing and wrong a lot of the time (example recently in this thread, examples multiple times for me in the last few weeks of bugs I've logged that QA teams tried to point us to an incorrect IssueTracker instead). The original bug reports are correct, the IssueTracker is "mostly correct".
    3. Missing most of the information about the actual bug, the reproduction case, etc: again, only Unity staff are allowed to see this: us developers are blocked from seeing it (e.g. I see IssueTrackers syaing "attached reproduction case" but the site has no link to see/view/download those?)
    4. Missing any/all extra information provided by Unity during the QA process (about 50% of the bugs I've logged QA has needed extra info in followup emails - but all of that is removed from the IssueTracker, even though other developers would benefit from it.
     
  22. a436t4ataf

    a436t4ataf

    Joined:
    May 19, 2013
    Posts:
    1,256
    (I only mention it here in this thread as a warning to everyone not to rely too much on my summary post - only you can tell us the true situation, since we're not able to see/verify any of the Case numbers posted in this thread).

    ...unless, as requested above, there's a link somewhere where we can see the current status of this feature, it's known bugs, etc?)
     
  23. LaneFox

    LaneFox

    Joined:
    Jun 29, 2011
    Posts:
    6,867
    phobos2077 likes this.
  24. LaneFox

    LaneFox

    Joined:
    Jun 29, 2011
    Posts:
    6,867
    So this was later rejected as By Design since it was never intended to give the functionality of dragging interfaces around in the Inspector.

    The reason this is confusing is because of the way the editor experience trains you to think. For instance if I drag a
    GameObject
    into a field for
    Potato
    then it 'just works' and does a GetComponent on the object being dragged for me and throws the result into the field.

    That doesn't work for interfaces because there's no actual data so for a dirty hack you have to use a backing field and custom drawers to circumvent the issue. The non-support for serialization on interfaces is understood (but not unsolvable because there are solutions for doing exactly that [Odin]), but it would be useful if the
    [SerializeReference]
    did not have the blanket statement that "interfaces are supported" while they actually are not supported in the inspector - where designers spend all of their time. A better statement would maybe be "interfaces have limited support".
     
    phobos2077 and a436t4ataf like this.
  25. a436t4ataf

    a436t4ataf

    Joined:
    May 19, 2013
    Posts:
    1,256
    I'd recommend splitting the docs not along interfaces/classes but along code-access/UI-access. Note that your expectations about interfaces could equally be applied to classes! SerializeReferences is serializing a reference (as per the name :)), but the Editor does not allow you to interact with the reference, it only interacts with the concrete class/data from de-referencing that reference.

    So perhaps:

    "For script access (read/assign), all classes except those deriving from Unity.Object are supported, and all interfaces are supported.
    For Editor access (default inspector), all references are treated as concrete data, and cannot be shared/cross-referenced/assigned unless you write custom PropertyDrawer/Inspector code to provide that functionality yourself"
     
  26. SonicBloomEric

    SonicBloomEric

    Joined:
    Sep 11, 2014
    Posts:
    917
    Can you please expand upon this? I admit that I don't understand what you're driving at based on this explanation. You can easily create a MonoBehaviour instance that has zero fields in it and the Inspector will happily let you see/modify it when it is set inside field on another MonoBehaviour/ScriptableObject (by "modify" I simply mean "delete the reference").

    Perhaps a simplified code example that showcases your "backing field" solution will help further illuminate the specific scenario you're describing?
     
    LucasHehir likes this.
  27. LaneFox

    LaneFox

    Joined:
    Jun 29, 2011
    Posts:
    6,867
    The goal would be to have serialized interface references like you would have a serialized reference to anything else, like MonoBehaviors and ScriptableObjects, and various Asset files.

    Since
    [SerializeReference]
    does not actually provide this functionality in the inspector like one would expect something called SerializeReference to do - you need to build your own drawer to support it, but you can't serialize an interface since its ... an interface.

    The expectation of the attribute would be to automatically detect the class that is implementing the interface and reference that instead - and that would be valid. Again, that is not what they're trying to do, even though it seems like it should.

    To make this functionality a reality it's necessary to have something to serialize. One approach requires a backing field.

    Code (csharp):
    1. public IPotato MyPotato => m_MyPotato as IPotato;
    2. [SerializeField] private Object m_MyPotato;
    By creating and adding another attribute and a custom property drawer it is possible to draw, validate, and serialize the backing field with built-in Object support. This is not ideal, but works.

    The result is 2x the cost of calling a method for each call to
    MyPotato
    . Not really much to worry about, in the end.
     
  28. SonicBloomEric

    SonicBloomEric

    Joined:
    Sep 11, 2014
    Posts:
    917
    Ahh, so specifically you are talking about UnityObject here, yes? And what's more, your "backing field" solution actually involves throwing away the [SerializeReference] attribute altogether, right?

    I am asking for context. For someone who is not familiar with your code, the immediate question becomes: "how does adding a backing field to an interface-typed field get things to work with [SerializeReference]?"

    In addition, it is important to note that [at time of writing] the [SerializeReference] attribute can't be used with types that derive from UnityObject, yeah?
     
  29. LaneFox

    LaneFox

    Joined:
    Jun 29, 2011
    Posts:
    6,867
    That's all correct. My issue is if an attribute that is designed to serialize interface references can actually do that, then why can't I use it to serialize a reference to an interface in the Inspector?.
     
    phobos2077 likes this.
  30. TextusGames

    TextusGames

    Joined:
    Dec 8, 2016
    Posts:
    415
    You can serialize objects of ISomeInterface. But only objects that are not derived from UnityEngine.Object.
    You can download this project in order to understand capabilities of [SerializeReference] better.
    https://forum.unity.com/threads/serializereference-genericserializedreferenceinspectorui.813366/
     
    Last edited: Aug 7, 2020
  31. MaskedMouse

    MaskedMouse

    Joined:
    Jul 8, 2014
    Posts:
    673
    So confusing. I am busy with refactoring some functionality and actually hoped to serialize a public interface field with a MonoBehaviour based component using the interface. But apparently that is not how SerializeReference is designed?

    Like I was actually hoping to be able to serialize the
    public SomeInterface Interface
    in the
    SomeBehaviour
    .

    Code (CSharp):
    1. public interface SomeInterface
    2. {
    3.     void DoWork();
    4. }
    5.  
    6. public class SomeBehaviour : MonoBehaviour
    7. {
    8.     [SerializeReference]
    9.     public SomeInterface Interface;
    10.  
    11.     public void Start() => Interface.DoWork();
    12. }
    13.  
    14. public class SomeComponentA : MonoBehaviour, SomeInterface
    15. {
    16.     public void DoWork()
    17.     {
    18.         Debug.Log("Work on Component A");
    19.     }
    20. }
    21.  
    22. public class SomeComponentB : MonoBehaviour, SomeInterface
    23. {
    24.     public void DoWork()
    25.     {
    26.         Debug.Log($"Work on Component B");
    27.     }
    28. }
     
  32. a436t4ataf

    a436t4ataf

    Joined:
    May 19, 2013
    Posts:
    1,256
    What is confusing? The documentation clearly states that:

    ...is impossible.

    A lot of people seem to be struggling to understand the documentation, which has always been up-front about this feature and what it does(n't) do. Is the preamble about it's use for serializing graph-structures not obvious enough? Does it need to be more aggressive?

    The docs could definitely be simpler, or more aggressive about explaining what it's NOT for, but I felt that for the target audience (anyone doing advanced tricks with Serialization like this should already be high level of expertise with Unity first) it was plenty clear enough.

    Maybe the docs need a warning "This is an advanced feature. Do not use unless you are very sure what it does, and that it's the right feature for your use-case"?
     
    phobos2077 likes this.
  33. MaskedMouse

    MaskedMouse

    Joined:
    Jul 8, 2014
    Posts:
    673
    I wasn't talking about documentation. But rather by reading around, got me confused as it gave the impression that this would be possible. But after reading the actual documentation yeah sure, it is stated
    unless the field type derives from [UnityEngine.Object]
    .
    Instead of confusing, disappointment would've been a better wording.

    Impossible with this attribute yes, not impossible with Odin Serializer though. You can pretty much serialize anything with that (including interfaces). But at my work place they don't have Odin purchased, so I cannot use it.

    If people read the documentation at all. I don't do it at all times and in this case I didn't even bother to read it until after I found out my use case didn't work. Before I only skimmed through a blog post about being able to serialize more and reading around a bit on forum. Decided to try it out, to then only be disappointed to find out that the thing I'm trying to do doesn't work that way.
    Even with 5+ years experience, trial and error has been more my way of testing things out than reading documentation. In this case it just lead me to disappointment that I can't use it the way I thought it could. So I ended up using a base abstract class. Downside is that when making a serialized field it has to be of that base class instead of a simple interface. Anything else that doesn't inherit from that base class you need to work around it, to implement the functionality.
     
  34. a436t4ataf

    a436t4ataf

    Joined:
    May 19, 2013
    Posts:
    1,256
    I guess the name of the attribute is misleading as well? Nothing in the name of it reveals that it would be exclusive of Unity.Object (instead of inclusive)...
     
  35. oscarAbraham

    oscarAbraham

    Joined:
    Jan 7, 2013
    Posts:
    75
    Hi, sorry to bother you. Me and a colleague are trying to decide if I should implement something using SerializeReference. It seems like what we need, but we need this issue with non serialized fields resetting to be fixed in order to be able to use it.

    Is there an ETA on this fix that you could give us, so that we could decide if we should wait or do it another way? Thanks a lot for your time.
     
    TextusGames, Elringus, Jes28 and 2 others like this.
  36. SleepySeed

    SleepySeed

    Joined:
    Mar 21, 2019
    Posts:
    1
    I have the same or similar issue using 2019.4.10:
    Only the default UnityEvent without Argument works and is displayed correctly in the Inspector.
    When serializing an object of the same type as the target field of the [SerializeReference] - Attribute, it also works as intended. But thats not the idea of [SerializeReference], I could use [SerializeField] instead.

    When the [SerializeReference] field is an interface or any base type, UnityEvent<T> derivations are displayed as a default UnityEvent and won´t work.


    Code (CSharp):
    1. [Serializable]
    2. public class BoolEvent : UnityEvent<bool>
    3. { }
    4.  
    5. public interface IBoolEventWrap
    6. {
    7.     void Invoke(bool value);
    8. }
    9.  
    10. [Serializable]
    11. public class BoolEventWrap : IBoolEventWrap
    12. {
    13.  
    14.     [SerializeField]
    15.     private BoolEvent boolEvent;
    16.  
    17.     public void Invoke(bool value)
    18.     {
    19.         boolEvent.Invoke(value);
    20.     }
    21.  
    22. }
    23.  
    24.  
    25. public class ScriptWithSerializeReference : MonoBehaviour
    26. {
    27.  
    28.     //SerializeReference to Interface or Base Class - BROKEN
    29.     [SerializeReference]
    30.     private IBoolEventWrap iBoolEventRef = new BoolEventWrap();
    31.  
    32.     //SerializeReference to explicit Class - WORKS
    33.     [SerializeReference]
    34.     private BoolEventWrap boolEventRef = new BoolEventWrap();
    35.  
    36.     // WORKS
    37.     [SerializeField]
    38.     private BoolEventWrap boolEvent;
    39.  
    40. }
     
    oscarAbraham likes this.
  37. brunocoimbra

    brunocoimbra

    Joined:
    Sep 2, 2015
    Posts:
    597
    If anyone interested, I made a simple ReferenceField<T> type where it shows either the serialized reference (if the reference is not an UnityEngine.Object) or the UnityEngine.Object reference on the inspector. One file is the type and another one the drawer (that should be placed on an Editor assembly/folder.

    Use and edit it as you wish, consider it being in the public domain.
     

    Attached Files:

    oscarAbraham likes this.
  38. oscarAbraham

    oscarAbraham

    Joined:
    Jan 7, 2013
    Posts:
    75
    I've found some issues that break serialized references when overriding prefabs. Some the issues I've found are very clearly bugs; I can't imagine any way they could be expected behaviors. Sometimes fields marked as overridden are still modified when their counterpart in a prefab changes, sometimes they get stuck and cannot be reverted back no matter how much you click Revert, sometimes nested lists get emptied out of nowhere, references are lost and some other smaller weird behaviors. There are a lot of different ways of triggering this issues, like doing an undo, nesting classes, having multiple references to the same object, assigning null to fields, reordering or resizing arrays with certain kinds of subclasses, modifying a script etc.

    I think a root cause of this could be that overridden serialized references are serialized with a very different topology from the way they are serialized on prefab assets or non-prefab components. Normally, each serialized field just stores an index, then, separately, there's a list of object references serialized with their data and their type. I think that makes perfect sense. It's another story with overridden fields, though, which store each of their changes by writing the whole property path and its new value. So, when the shape of data differs between instances and prefabs, a good amount bad things can happen. I think some of this issues could be fixed by simply changing the order in which fields are deserialized; sometimes child properties seem to be deserialized before their parents, so they get lost easily when the parent is overriden. I'd bet some other issues would be harder to fix, though.

    Edit:
    I found some of this had actually been mentioned in this thread. That's my bad. I also found this issue which seems to be related to the problems I'm having. It's marked as fixed for 2020.2 and in review for 2020.1 and 2019.4. I hope it works and gets passed for the non beta versions soon. But things doesn't seem as dire as I thought. I'll do some tests on the 2020.2 to see if my issues disappear or at least get smaller there. Sorry for noticing the information so late.

    Edit 2:
    No, it doesn't fix it. :/ If, for example, a field with the SR attribute is null on the prefab, but is overridden to contain an object in an instance, and said object has a nested field with the same attribute, that nested field still gets lost when reloading or doing an undo. This makes it practically impossible to use nested or relational structures in Monobehaviours. It can even cause some issues with simple lists if certain sequences of actions are taken.

    I'll try to make time to submit a bug report with a project that demonstrates the most relevant triggers I've found for these issues later. Something tells me it won't be easy to fix, though. There's this other related issue, which is marked as postponed, about not being able to override types of serialized references; the thing is, I'm able to do that just fine and when I open the scene file in a text editor, there is a record of types being overridden. Nevertheless, there's a note in this issue says: "This is a known limitation due to how modifications are stored on prefab instances. Documentation will be corrected to mention this". It makes me think I shouldn't hope the issues I'm dealing with could be solved anytime soon. Also, I really searched the docs and I think there's still no mention of any prefab problems; a note about it could have saved me a lot of time.
     
    Last edited: Oct 15, 2020
    phobos2077 likes this.
  39. net8floz

    net8floz

    Joined:
    Oct 21, 2017
    Posts:
    37
    Kind of a weird question and I think i've gone through the whole thread. I've found that [SerializeReference] , as the name implies , serializes reference types and not value types. Is there a reason for this? I've found the meta data will record the id of the reference and even the type but just refuses to store the data.


    Code (CSharp):
    1. public class IntWrap {
    2.     public int Value;
    3. }
    4.  
    5. [SerializeReference] object val;
    6.  
    7. // type will be recorded, reference will be indexed, data will not be added to the asset ( even shows the value in the inspector just not the .asset !)
    8. val = 32;
    9.  
    10. // serializes and unserializes perfectly
    11. val = new IntWrap() { value = 32 };
    12.  
    13.  
    My goal here is to just shove a value in an object and call it a day. ( excluding unity objects )
     
  40. Qriva

    Qriva

    Joined:
    Jun 30, 2019
    Posts:
    119
    I also would like to know if there is any ETA for fixing bugs in SerializeReference.

    Someone from unity would have to explain why it is implemented exactly like this, but as I know, SerializeReference is just kind of modifier attribute for Serializable classes (only). I think unity serialization system has no such function, becuase storing data as c# objects (or rather as guessed type) would be bad design.
     
    oscarAbraham likes this.
  41. net8floz

    net8floz

    Joined:
    Oct 21, 2017
    Posts:
    37
    It's certainly not something you'd want to do often but there times, often editor only times, when this would be a total blessing. And since the type is stored but not the data it's kind of a little weird. And again I'm just talking about value types like an int. Things that are naturally serializable. Even just implementing it as a editor only type attribute would be awesome.
     
    oscarAbraham likes this.
  42. Tkrain42

    Tkrain42

    Joined:
    Jul 25, 2015
    Posts:
    8
    Until you try
    Code (CSharp):
    1.                 BinaryFormatter formatter = new BinaryFormatter();
    2.                 formatter.Serialize(stream, state);
    A Vector3 will crash this.
     
    Bastienre4 and phobos2077 like this.
  43. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    5,052
    Have you filed a bug report for this?
     
  44. Gooren

    Gooren

    Joined:
    Nov 20, 2015
    Posts:
    275
    I'm getting the following error: "Invalid serialize reference type dependency name: '_Library.Gameplay.Interaction.PrismaticJointMechanismParameters, Library Gameplay, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'"

    When I wanted to create a repro project, I was not even able to get the most basic example scenario to work - meaning I can only see the field name in the inspector. I just copy pasted the code into a new project o_O

    NOTE: Unity 2019.4.13f1
     
  45. Silly_Rollo

    Silly_Rollo

    Joined:
    Dec 21, 2012
    Posts:
    498
    issue 1193322 really sucks for me, is there any news on when the fix is coming to 2020.1?
     
    Ghat-Smith and Jes28 like this.
  46. DeepShade

    DeepShade

    Joined:
    Apr 10, 2018
    Posts:
    8
    I found another issue while using [SerializeReference] that really concerns me. I have already filed a bug report:
    Tested in 2020.1.12f1, 2020.1.3f1, 2020.2.0b10

    Steps to reproduce:
    1. Create a new empty Unity project
    2. Copy the attached file 'ForbiddenAssignment.cs' to the asset folder of the newly created project
    3. In addition open the file in your preferred IDE
    4. Create an empty GameObject in any scene and add the 'ForbiddenAssignment' component to it
    5. Observe that a value of type 'TestClass' is assigned to the field 'ReferenceField' of 'ForbiddenAssgnment' which is of type 'object' and marked with the 'SerializeReference'.
    6. Switch to your IDE and change the comment-out the first line in 'ForbiddenAssignment.cs' which reads '#define FIRST_VERSION'. This changes the type of the field 'ReferenceField' from 'object' to 'AbstractClass'
    7. Save the file and switch to Unity again and wait until it has compiled the code
    8. Observe in the inspector that there is still a value assigned to 'ReferenceField' which has a itself a field of type 'int' with the name 'FieldInTestClass' as it is declared in 'TestClass'. Note that 'TestClass' is not derived from 'AbstractClass'
    9. Enter playmode. The console should print:
    - "Is the field value null? - false"
    - "Is the value of the field assignable to the field type? - false"
    - "This is wrong!"
    In all my tests, this is followed by a crash of the editor caused by the call to method 'AbstractClass.FinallyCrash'

    Description:
    It should be clear at this point that this is serious issue. An instance was assigned to a field that is not assignable to the field's type under all other circumstances. Further more no error or warning was presented to the user. It was even possible to invoke a method of an abstract type that was never instanciated.

    Assumption:
    The value assigned to 'ReferenceField' should be set to null after it's field type was changed.

    Code (CSharp):
    1. #define FIRST_VERSION
    2.  
    3. using System;
    4. using System.Collections;
    5. using UnityEngine;
    6.  
    7. public class ForbiddenAssignment : MonoBehaviour
    8. {
    9. #if FIRST_VERSION
    10.     [SerializeReference]
    11.     public object ReferenceField = new TestClass();
    12. #else
    13.     [SerializeReference]
    14.     public AbstractClass ReferenceField;
    15.  
    16.  
    17.     IEnumerator Start()
    18.     {
    19.         Debug.Log("Is the field value null? - " + (ReferenceField == null));
    20.         Debug.Log("Is the value of the field assignable to the field type? - " + typeof(AbstractClass).IsAssignableFrom(ReferenceField.GetType()));
    21.  
    22.         // This is surprisingly also still working!
    23.         ReferenceField.LogSomething();
    24.  
    25.         yield return new WaitForSeconds(3);
    26.  
    27.         // This should finally end this misery!
    28.         ReferenceField.FinallyCrash();
    29.     }
    30. #endif
    31. }
    32.  
    33. [Serializable]
    34. public abstract class AbstractClass
    35. {
    36.     public void LogSomething()
    37.     {
    38.         Debug.Log("This is wrong!");
    39.     }
    40.  
    41.     public abstract void FinallyCrash();
    42. }
    43.  
    44. [Serializable]
    45. public class TestClass
    46. {
    47.     public int FieldInTestClass;
    48. }
     
    phobos2077 and Ghat-Smith like this.
  47. Qriva

    Qriva

    Joined:
    Jun 30, 2019
    Posts:
    119
    I am not sure if this is a bug, first of all this attribute is probably not allowed for object type fields, second normally fields cannot change type. This is more like editor serialization bug if any.
     
  48. DeepShade

    DeepShade

    Joined:
    Apr 10, 2018
    Posts:
    8
    First of all, you should at least read the official documentation before you start speculating
    Second, I'm not sure if you really got the point. Of course this is a bug. Imagine you could write:
    Code (CSharp):
    1. List<int> list = new HashSet<string>()
    in C# and it would actually compile. This bug has nothing to do with
    object
    in particular. This is possible for any combination of types.

    Third, so you are saying that it is uncommon to change the type or name of a field while programming. But let's leave out the discussion if this is really that unusal as you are implying. What I find more interesting is that you seem to suggest that this should not be considered a bug because it is caused by something that you think does not happen often. If you don't see to what kind of serious, hard to find bugs this behaviour may lead you haven't read the code carefully enough. The crash at the end may be the best outcome of the whole issue.

    And by the way: How can something that causes the editor to crash not be considered a bug?
     
    Jes28 and phobos2077 like this.
  49. Qriva

    Qriva

    Joined:
    Jun 30, 2019
    Posts:
    119
    Actually I did check the documentation and I could not find that line before. Maybe it was some old version, but most likely I was just blind somehow - anyway my bad. Also, actually your last line is very right and enough to consider it as a bug, just ignore what i wrote about "it's not a bug", it's bullshit.

    But could you explain that part about compiling code? I am not expert, I don't understand that.
    If you put your example code into unity, then it will not allow you to proceed until you fix it (as it's not valid).
    Obviously you can try to compile any invalid code like that, but this way you probably could break editor in many different ways without need of any special attribute or anything else.
    Some time ago I made custom tool and I tried to put class field in #if UNITY_EDITOR block and (as it turned out) it was not allowed, becuase definition/number of fields can not change between assemblies and this is why i said "normally fields cannot change type".
    Actually it turned out behaviour described above happens in manual edit too. Unity serialization system usually prevent incompatible serialized data to break something, but this time it forces old data to be initialized in the invalid field what is wrong.

    I assumed system object is not valid and becuase compiler and serializer is stupid I would not be surprised that it does not work, if you forced it do things it can't. If you throw brick into washing machine, you should not be surprised it exploded. Of course in reality editor should not crash, but throw some error instead.
     
  50. DeepShade

    DeepShade

    Joined:
    Apr 10, 2018
    Posts:
    8
    Yeah your are right. Errors or missing details in the official documentation are unfortunately more common than not.

    What I was trying to explain is that C# is a type safe language. This is a strong guarantee for the code we are writing because it enforces the existence and signature of type members at compile time. This is not true for non type safe languages like javascript. Imagine you have some kind of vector class and you want to do some kind of calculation:

    Code (CSharp):
    1. public float Calculate(MyVector vector)
    2. {
    3.      return vector.x + vector.z;
    4. }
    Type safety does not guarantee you that your calculation is correct but it will guarantee you that
    MyVector
    has a member with the name
    x
    and a member with the name
    z
    , that they can be added together using the
    +
    operator and that this operator returns a result that is equal to or at least implicitly convertable to
    float
    . In a non type safe language, there would be none of the above mentioned guarantees. It would be unknown until the code is executed if
    MyVector
    actually has a
    z
    or even a
    x
    component and if these return some numerical value, a string or maybe GameObject.

    This is an integral part of the C# language and it is very, very hard to violate. Not with reflection and not even (at least to my knowledge) when using unsafe code. I didn't even know that it is possble until the developers at Unity managed to achieve the unthinkable. Now it is possible to create abominations of objects that defy any description...

    ...I mean ... because they use the wrong type information at runtime. Sorry got carried away a little bit.

    If the guys at Unity just set the instance to null instead everything will be fine. Should be an easy fix!
     
unityunity