- Home /
Serializating a base class array to a prefab
I have been dealing with this issue for the whole week and I am kind of stuck and out of ideas.
I am working in a quick item editor. Each item may have one or more properties. These properties have all a common parent since they have common properties. Each child may also have particular properties.
I want to use the editor to show the properties array, edit it, and when finished, save the created gameobject to a prefab.
I almost have it working but I am facing a problem:
If I make MyBaseClass not to inherit from ScriptableObject (see comments on code below), everything works almost like a charm, but the child objects are casted to the parent class and they will remain like that forever. This problem was already stated here and was supposed to be solved with the next option, which is:
If I make MyBaseClass to inherit from ScriptableObject everything works fine before prefab creation, but then after creating the prefab, the array seems to be in a corrupted state. It seems that the CustomEditor is no longer correctly executed for that prefab.
This is my code, simplified for a better understanding. Just create each script separately (it should run as it is) and drag the SerializeMe.cs to a gameobject to reproduce the scenery. Remember to store SerializeMeInspector.cs into the Editor folder.
SerializeMe.cs
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
[Serializable]
public class SerializeMe : MonoBehaviour
{
[SerializeField]
public List<MyBaseClass> m_Instances;
public void OnEnable ()
{
if (m_Instances == null)
m_Instances = new List<MyBaseClass>();
hideFlags = HideFlags.HideAndDontSave;
}
}
MyBaseClass.cs
using UnityEngine;
using System;
[Serializable]
public class MyBaseClass : ScriptableObject
//public class MyBaseClass
{
[SerializeField]
public int m_IntField;
public void OnEnable()
{
hideFlags = HideFlags.HideAndDontSave;
}
}
ChildClass.cs
using UnityEngine;
using System;
[Serializable]
public class ChildClass : MyBaseClass
{
[SerializeField]
public float m_FloatField;
}
SerializeMeInspector.cs (stored in the Editor folder)
using UnityEngine;
using System.Collections.Generic;
using System;
[CustomEditor(typeof(SerializeMe))]
public class SerializeMeInspector : Editor
{
SerializedProperty SP_m_Instances;
public void OnEnable()
{
SP_m_Instances = serializedObject.FindProperty ("m_Instances");
}
public override void OnInspectorGUI()
{
serializedObject.Update ();
if (GUILayout.Button ("Add Base"))
{
//(target as SerializeMe).m_Instances.Add(new MyBaseClass());
(target as SerializeMe).m_Instances.Add(
(MyBaseClass) ScriptableObject.CreateInstance("MyBaseClass"));
}
if (GUILayout.Button ("Add Child"))
{
//(target as SerializeMe).m_Instances.Add(new ChildClass());
(target as SerializeMe).m_Instances.Add(
(MyBaseClass) ScriptableObject.CreateInstance("ChildClass"));
}
for (int i = 0; i < SP_m_Instances.arraySize; i++)
{
EditorGUILayout.Foldout(false,"Element #"+i);
MyBaseClass parent = (target as SerializeMe).m_Instances[i];
// Base common display
parent.m_IntField = EditorGUILayout.IntField(
"Base prop", parent.m_IntField);
// Child display if casting is a success
ChildClass child;
try
{
child = (ChildClass) parent;
}
catch (InvalidCastException)
{
child = null;
}
if (child != null)
{
child.m_FloatField = EditorGUILayout.FloatField(
"Child prop", child.m_FloatField);
}
}
serializedObject.ApplyModifiedProperties ();
}
}
I'd really appreciate any ideas or help with this.
Thank you very much in advance.
EDITED: Some code added as suggested by Bunny83, but still not working
Answer by Bunny83 · Sep 25, 2013 at 07:22 PM
You simply forgot to set the hideflags in OnEnable of your MyBaseClass.
I have already set hideflags in OnEnable in $$anonymous$$yBaseClass, but it is still not working. As soon as I drag the object and create a prefab, the prefab get corrupted and it doesn't display the elements correctly. It only displays the first element.
I have been doing some debugging and I have realized that, at this line in Serialize$$anonymous$$eInspector.cs, inside the 'for' loop:
$$anonymous$$yBaseClass parent = (target as Serialize$$anonymous$$e).m_Instances[i];
It happens that parent equals null, but SP_m_Instances.arraySize has the right value, so it kind of stops processing the file. That's why it only displays the first item.
Any ideas on what might be happening?
Answer by alvaro-em · Sep 26, 2013 at 04:47 PM
I have found this great post about this exact issue. It seems that Unity does not serialize polymorphic types properly. In this post, a kind of workaround is offered. I will try it and let you know the results.
I am still willing to hear any other idea to get rid of this issue.
Additionally, you can vote for an idea to solve this issue right here.
Your answer
Follow this Question
Related Questions
Help with using JsonUtility.FromJsonOverwrite 1 Answer
Saving runtime created avatar 1 Answer
How do I save; then load an array of Lists or a List of arrays (of ints)? 2 Answers
How to effect and apply a common material to children individually... 2 Answers
RayCast Collision between 2 game objects (of the same prefab) 1 Answer