Search Unity

Bug [SerializeReference] Can NOT save new data if old class deleted

Discussion in 'Scripting' started by yu_yang, Aug 9, 2021.

  1. yu_yang

    yu_yang

    Joined:
    May 3, 2015
    Posts:
    85
    Code (CSharp):
    1.  
    2. [Serializable] class A { }
    3. [Serializable] class B : A { }
    4. [Serializable] class C : A { }
    5.  
    6. public class MyComponent : MonoBehaviour
    7. {
    8.     [SerializeReference]
    9.     A data;
    10.  
    11.     [ContextMenu("Set Data")]
    12.     void SetData()
    13.     {
    14.         Undo.RecordObject(this, "Set Data");
    15.         data = new B();
    16.     }
    17. }
    18.  
    Add MyComponent to a GameObject, select "Set Data", then save the project;
    Delete the definition of class B, modify "data = new B()" to "data = new C()" in SetData();
    select "Set Data" again, save the project;
    Reopen the project, data is not saved, in fact you can not save new data any more.
     
    Last edited: Aug 11, 2021
  2. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,989
    Well, you don't properly save your data at all ^^. You should do something like:

    Code (CSharp):
    1.     [ContextMenu("Set Data")]
    2.     void SetData()
    3.     {
    4.         Undo,RecordObject(this);
    5.         data = new B();
    6.     }
     
  3. yu_yang

    yu_yang

    Joined:
    May 3, 2015
    Posts:
    85
    Thanks, Undo.RecordObject is used for Undo command, I know this. My question is, you can not save new data if old class deleted, but if change data without deleting old class, then you can save it.
     
  4. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    7,842
    I mean aside from not calling SetDirty() or Undo.RecordObject(), in what instance would this come up?
     
  5. yu_yang

    yu_yang

    Joined:
    May 3, 2015
    Posts:
    85
    This will always happen.
     
  6. Laperen

    Laperen

    Joined:
    Feb 1, 2016
    Posts:
    1,065
    I am assuming classes B and C have additional stuff built ontop of A. If the data you are intending to keep is unique to B or C, then they wont be saved by the data variable of type A. It should save data that can be held by A if you cast B or C into A.

    Inheritance in this instance should be viewed as a one-way street, the base is unable to keep properties unique to its inheritors.

    If what I've hypothesized isn't the case however, then I am also stumped.
     
  7. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,989
    Yes, but it also ensures that the data is serialized, which is it's main purpose. You can not simply modify instance data and expect unity to magically serialize that data.

    Also as spiney199 said, it's relevant where this data field is used and where the contained object is stored.
     
  8. yu_yang

    yu_yang

    Joined:
    May 3, 2015
    Posts:
    85
    Sorry for the wrong sample code, Undo.RecordObject now is added.
    The issue I want to report is this:
    upload_2021-8-11_22-52-14.png
     
  9. yu_yang

    yu_yang

    Joined:
    May 3, 2015
    Posts:
    85
    After you set the new data and save it, open the scene file with a text editor, you will find that the saved data type is still the old type (class B), the new data is not saved. In fact, YOU CAN NOT SAVE NEW DATA FOREVER!