ScriptableObject and Serialization

I’ve been working on some tool development for a project in Unity, and have so far been very impressed with the flexibility that ScriptableObject, and the whole EditorWindow system provide. I’ve hit a snag though, and wanted some advice on how to proceed.

The basic idea is this:

[System.Serializable]
class Container : ScriptableObject
{
  Base[] stuff = new Base[0];
}

[System.Serializable]
class Base
{
  Object dataSource = null;

  public virtual bool Foo() { return false; }
}

[System.Serializable]
class A : Base
{
  public override bool Foo() { return true; }
}

I can create a disk asset for Container with AssetDatabase.CreateAsset( new Container(), path ), and I can add instances of A to Container’s stuff array. Everything works as expected until I close the editor and restart the project. At this point all of the A’s become “Base” objects (And the behaviour of the virtual functions switches back to their defaults).

In order to get the type to be preserved, I have to either make Base as ScriptableObject, and save it to disk (either by adding it to the same asset as Container, or creating a new asset for it).

Alternatively I could drop the inheritance and instead of having an Array of Base, I can have an array of A, and of B, and of C, etc… However since A, B, and C will have common interfaces and Unity doesn’t properly support Generics, I might find myself having to manage a lot of code.

Is there any way to get serialization to encode type information so that you only have to have the ‘container’ class as a ScriptableObject (and disk asset), and be able to make use of inheritance w.r.t. code reuse and virtual functions. Or am I missing the point entirely and serialization was only meant to work with just data.

Armed with a better understanding of what’s going on, I was able to find some forum threads that answer most of the questions I had. As I understand it:

Objects which are using [System.Serializable] cannot be inherited. If you need inheritance, make the base class derive from ScriptableObject.

However, ScriptableObjects aren’t serialized via their containing object, the object reference is lost if the ScriptableObject isn’t saved to a .asset file via the AssetDatabase. There is no way around this? I suppose HideFlag.HideInHierarchy could be used to prevent clutter if you’re producing a lot of ScriptableObject instances that need to be saved, let your EditorWindow deal with the asset management.

Neither ScriptableObjects nor [System.Serializable] objects seem to serialize their private data, is there any way around this? C# suggests that private data should be serialized unless marked with [System.NonSerialized]. Is there no way to hide data from the user while still serializing it short of using the HideFlag.NotEditable to prevent it from being modified by the inspector?

@ChrisH: Does .NET serialization work in Unity the way it does in plain old mono? I’ve already seen some counter examples, as noted above.

Did anyone find a solution to this?

~ce

what’s about [HideInInspector]

I think you want ScriptableObject.hideFlags = HideFlags.HideInHierarchy