Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Unhappy Derived Types!

Discussion in 'Scripting' started by BitVenom, Aug 20, 2008.

  1. BitVenom

    BitVenom

    Joined:
    Jan 30, 2008
    Posts:
    19
    I'll try to be brief, but as of now... I am just _very_ confused... and anyone that reads this and has advice, I'd love to hear it.

    Code (csharp):
    1.  
    2. [System.Serializable]
    3. public class BaseData
    4. {
    5.     public int BaseInt = -1;
    6. }
    7.  
    8. [System.Serializable]
    9. public class DeriveData : BaseData
    10. {
    11.     public int DerInt = 2;
    12. }
    13.  
    14. //... Inside a Monobehaviour:
    15. public class UseData : MonoBehaviour
    16. {
    17.     public BaseData[] SomeData = null;
    18.  
    19.     public void FillData(void)
    20.     {
    21.         SomeData = new BaseData[10];
    22.         for (int i=0; i<SomeData.Length; i++)
    23.         {
    24.             DeriveData MakeData = new DeriveData();
    25.             Debug.Log(MakeData.ToString());   // "DeriveData"
    26.             SomeData[i] = MakeData;
    27.             Debug.Log(SomeData[i]);     // "DeriveData"
    28.         }
    29.     }
    30.  
    31.     public void LookData(void)
    32.     {
    33.         for (int i=0; i<SomeData.Length; i++)
    34.         {
    35.             Debug.Log(SomeData[i]);     // "BaseData"
    36.             BaseData MakeData = SomeData[i];
    37.             Debug.Log(MakeData.ToString());   // "BaseData"
    38.             DeriveData HopeData = SomeData[i] as DeriveData;
    39.             // HopeData is NULL?!!?!!!
    40.         }
    41.     }
    42. }
    43.  
    Placing a derived-class into a base-class array, _seems_ to be okay. As the first routine proves (the ToString of the base-class array entry returns the derived-class name. Using it later, the data seems to have been cleaned/reformated. How? When? Wha?

    If I have a board game, and I have a grid (an array) of pieces... and I put derived board-game pieces into the array... that _should_ work. this is _really_ low level object oriented stuff. If you say 'use ArrayList' or something of the sort that's typeless, my issue is that Unity won't serialize that. Or atleast we can't get that to work. Maybe that's our failing? We can't just use Monobehaviours for this stuff, it's too heavy, and what we're doing is small, light stuff in great big sets...

    Ideas? Comments?

    BitVenom
     
  2. Dreamora

    Dreamora

    Joined:
    Apr 5, 2008
    Posts:
    26,601
    Did you try
    DeriveData HopeData = (DeriveData)SomeData;

    for the cast
     
  3. BitVenom

    BitVenom

    Joined:
    Jan 30, 2008
    Posts:
    19
    X = (xtype)Y;
    and
    X = Y as xtype;

    are almost the same... super-extra close in C#, actually... ?

    Also, notice in both functions:

    Code (csharp):
    1.  
    2. Debug.Log(SomeData[i]);     // "DeriveData"
    3.  
    the same call, SomeData.ToString(), without any changes in my script to that data... return 2 seperate types... so somewhere in behind the scenes, the data in the array gets 'downgraded' from derived to base... and I do _nothing_ to cause it.

    ?
     
  4. Talzor

    Talzor

    Joined:
    May 30, 2006
    Posts:
    197
    I did a few tests and there does indeed seem to be a bug in the serialization system whereby you can lose some type information. Since I'm actually precariously close to also being affected by this, I've filed it as a bug to Unity.
     
  5. BitVenom

    BitVenom

    Joined:
    Jan 30, 2008
    Posts:
    19
    Last night I went home (I take my work Macbook home with me often), and after moving from 'X = Y as X', to 'X = (X)Y', the bug went away. Fun. I must mis-understand the relevance of 'as'...

    I also had shutdown restarted Unity. That's all that changed. So... draw of that what you will.

    Cheers.
     
  6. BitVenom

    BitVenom

    Joined:
    Jan 30, 2008
    Posts:
    19
    Turns out this bug is still getting me... DAMN.

    But I think I know the reason...

    If I boot my scene, my code runs, creates the derived class, and continues... all is well.

    If I recompile script, or edit in Debug mode (not 100% sure about that one), the derived class reverts to base class, and I lose it all.

    I think, when Unity serializes the array out, either for a 'save' of the scene, or 'temp' to disable/reload script/enable a class, the serializer stores only the _base_ class. It says 'hey, this is an array of X', and so Y goes out the window =[

    Since 'arrays' in C# are really more correct 'pointer-arrays' from C/C++, and Unity is killing a very common use... what's the alternative? ArrayList won't serialize at all, right? A linked-list would be _horrible_ in my case... but that would work, in that references to class don't likely filter the type of object actually stored in the reference...

    Ideas?
    Dave
     
  7. Dreamora

    Dreamora

    Joined:
    Apr 5, 2008
    Posts:
    26,601
    Perhaps its a mono restriction.
    Here is the doc page: http://go-mono.com/docs/index.aspx

    Because thats what you are using, its not some Unity Magic.

    The own unity specific thing to serialize is that you can not serialize MonoBehaviors as they extend from a class thats not serializable.


    Is your code exactly the one above?
    Or do you have one using multiple files?
     
  8. BitVenom

    BitVenom

    Joined:
    Jan 30, 2008
    Posts:
    19
    That's just example code (typo-filled as it is!)...

    The real code is the basis for a very large system, 10k+ lines of code. Tools, etc.

    What does 'multiple files' have to do with it?
     
  9. Dreamora

    Dreamora

    Joined:
    Apr 5, 2008
    Posts:
    26,601
    well multiple files in different folders (especially within and outside the standard asset folder) could have issues (at worst, I assume the compiler should at least give you a warning when you fully recompile it) due to build order of scripts.
     
  10. BitVenom

    BitVenom

    Joined:
    Jan 30, 2008
    Posts:
    19
    Oh, no... no issue there..

    All in the same place, 2 files make up the 'basis' for this issue, ignore other derivants, side tools, etc...
     
  11. Dreamora

    Dreamora

    Joined:
    Apr 5, 2008
    Posts:
    26,601
  12. BitVenom

    BitVenom

    Joined:
    Jan 30, 2008
    Posts:
    19
    No... that's a guy talking about using Serialization. I understand it :) I have written more serialization code, for more languages than I can even recall. I am using Unity/Monos. And it's dumping my data...

    An example I just tested:

    I have my base class Array:

    public BaseData[] KeepMe;

    I also have a derived class member:

    public DerData HoldMe;

    I fill KeepMe with a set of DerDatas.
    I take the first (KeepMe[0]) and assign to to HoldMe.

    In -every- section of code after that, changes to HoldMe are reflected in KeepMe[0], and KeepMe[0].ToString returns 'DerData'. All is well.

    The moment I save, and come back... HoldMe's changes do not affect KeepMe[0], and KeepMe[0] has become a BaseData again.

    This means that the internal mechanics... that Arrays are reference arrays, works fine. And as references, they can refer to variant/derived types.

    But the serializer forces them into the declared class, and they never come back =[
     
  13. Dreamora

    Dreamora

    Joined:
    Apr 5, 2008
    Posts:
    26,601
  14. BitVenom

    BitVenom

    Joined:
    Jan 30, 2008
    Posts:
    19
    Funny, I saw exactly the same article :)

    Doesn't help... though, it seems to say that Lists are serializable in Net 3.0... Unity is using Mono 2, so i can see how that'd be broken =[
     
  15. Dreamora

    Dreamora

    Joined:
    Apr 5, 2008
    Posts:
    26,601
    I didn't post it because of the List part. More because perhaps the array serialization generates the same clone behavior.
     
  16. Joachim_Ante

    Joachim_Ante

    Unity Technologies

    Joined:
    Mar 16, 2005
    Posts:
    5,203
    Unity's serialization assumes that the type of an array does not change from element to element. This is one of the basic assumption in the system and allows us to very fast serialization, while at the same time allowing full backwards compatibility.

    This makes it impossible to use inheritance in a serialized embedded class. If you must use inheritance you have to inherit from ScriptableObject.

    If this has too big of an overhead for you then you might want to not use inheritance. It's amazing how much you can do with just having multiple arrays each with specific types, or god forbid an enum defining the type and interpreting data differently based on the enum.