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.
[System.Serializable]
public class BaseData
{
public int BaseInt = -1;
}
[System.Serializable]
public class DeriveData : BaseData
{
public int DerInt = 2;
}
//... Inside a Monobehaviour:
public class UseData : MonoBehaviour
{
public BaseData[] SomeData = null;
public void FillData(void)
{
SomeData = new BaseData[10];
for (int i=0; i<SomeData.Length; i++)
{
DeriveData MakeData = new DeriveData();
Debug.Log(MakeData.ToString()); // "DeriveData"
SomeData[i] = MakeData;
Debug.Log(SomeData[i]); // "DeriveData"
}
}
public void LookData(void)
{
for (int i=0; i<SomeData.Length; i++)
{
Debug.Log(SomeData[i]); // "BaseData"
BaseData MakeData = SomeData[i];
Debug.Log(MakeData.ToString()); // "BaseData"
DeriveData HopeData = SomeData[i] as DeriveData;
// HopeData is NULL?!!?!!!
}
}
}
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
Did you try
DeriveData HopeData = (DeriveData)SomeData*;*
for the cast
X = (xtype)Y;
and
X = Y as xtype;
are almost the same… super-extra close in C#, actually… ?
Also, notice in both functions:
Debug.Log(SomeData[i]); // "DeriveData"
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.*
?
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.
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.
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
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?
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?
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.
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…
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 =[
I guess you cast them before serialize and you cast them especially back when desirialize?
It might also be (even thought you most likely have more experience than I with serializable attribute etc) that you ran into the same problem as discussed here:
http://www.theserverside.net/discussions/thread.tss?thread_id=42285
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 =[
I didn’t post it because of the List part. More because perhaps the array serialization generates the same clone behavior.
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.