среда, 10 августа 2016 г.

Serialization with Polymorphism and Inheritance in Unity


In this article, I would like to share my experience in serialization of classes with inheritance and polymorphism in Unity. If you have some troubles with serialization of ScriptableObjects or with saving your data, it’s written to help you. Here I try to explain, how to serialize your data into asset. You can download sources for this tutorial here.


First of all, I want to say, that serialization WORKS for complex classes and SUPPORT inheritance. And I recommend to read this post about serialization. It uncovers the process of serialization, but doesn’t explain how to serialize your data into assets.

I was working on Dialog Editor for my project, and want to be able to save classes like this:


I faced with a lot of troubles when it come to serialization of polymorphic classes. Before Unity, I was working with Unreal Engine and never had any troubles with saving my data and didn’t expect, that it will be any problems with it in Unity. After a brief look into documentation, I tried to serialize some class, derived from base class and found, that serialization/deserialization didn't works as expected. There is a number of similar cases described on blogs and forums, and there was no clean solution. From the link given above, I've found, that for my case, I must use ScriptableObject as base class, in order to serialize polymorphic objects. ONLY objects, that derived from ScriptableObject and MonoBehaviour can be serialized/deserialized properly. Classes, that are inherited from ScriptableObject must be stored in separated files, so I've made some changes:


I decided to make a container for my classes:

Like it is in Unreal Engine, all data is serialized into assets.For example, you want to serialize some object A that owns object B. You should create two assets: one for object A and one for object B. For my case, I must create asset for every object in List. Fortunately, Unity let us to store assets into assets. But in comparsion to Unreal Engine, registering and creating new assets in Unity is much easier.

Here is a simple editor to create asset and edit serialized class:


hideFlags = HideFlags.HideInHierarchy is used to hide assets inside DialogContainer in Hierarchy view. Without this, we get something like that:


DialogContainer is finished and ready to be serialized or deserialized!



Troubleshooting

Until I have been writting this tutorial, I’ve made a number of mistakes, that make my code to works wrong. If you still have some troubles with serialization, read the text below and check your code for this errors.

  • When reloading my project, i’ve found, that my object wasn’t loaded with error “The associated script cannot be loaded”. If you have this error, it’s most likely, that you declare a few classes, derived from ScriptableObject in one file. You must keep every object, derived from ScriptableObject or MonoBehaviour in separate files to prevent this issue.
  • If some function isn’t called on derived object, it’s most likely, that you forget to make it virtual.
  • If some filed isn’t serialized, check that it’s market as [SerializeFiled].