- Home /
Serialize class that derives from abstract class
Earlier, I tried making characters using Scriptable Objects. But, the values would always change to null at runtime. I imagine I was doing something wrong. However, I have since decided to just make scripts for each character that derive from an abstract Character class.
Since I want to be able to easily add a sprite for each character's profile, how do I get the single field to show in the editor? I've tried Serializing the entire class, the field itself, and making it public, but nothing seems to work. Since the class derives from an abstract class and not a mono-behavior, this is much more difficult than I would have imagined.
Character.cs
public abstract class Character
{
public enum Job
{
Tank,
Healer,
Mercenary
}
public abstract string Name { get; set; }
public Job job;
public Sprite profilePicture;
public abstract int Health { get; set; }
public abstract int Attack { get; set; }
public abstract int Magic { get; set; }
public abstract int Defense { get; set; }
public abstract int Heal { get; set; }
public abstract int CritRate { get; set; }
public abstract int Resistance { get; set; }
}
Stella.cs
[System.Serializable] public class Stella : Character
{
[SerializeField] public new Sprite profilePicture;
public Stella()
{
Name = "Stella";
Health = 50;
Attack = 0;
Magic = 5;
Defense = 0;
Heal = 0;
CritRate = 5;
Resistance = 0;
job = Job.Mercenary;
}
public override string Name { get; set; }
public override int Health { get; set; }
public override int Attack { get; set; }
public override int Magic { get; set; }
public override int Defense { get; set; }
public override int Heal { get; set; }
public override int CritRate { get; set; }
public override int Resistance { get; set; }
}
Answer by Bunny83 · Jul 30, 2018 at 10:22 AM
Note that you said you originally derived your class from ScriptableObject. Is your abstract "Character" class derived from anything? Because Unity's serialization system does not support polymorphism for custom serializable classes. Only for ScriptableObjects and MonoBehaviours.
Using the "new" keyword in field declaration is in most cases not a good idea. That means you already have a field with that name and you introduce a new seperate field with the same name. So in the different contexts (parent or child class) the same name refers to different fields. The new keyword just hides derived members, though they are still there but can only be accessed through base.fieldname. Since a class derived from a base class actually is also a base class you don't need to declare the field again.
First i would recommend to read this page carefully. Second it you still need help with this you should include your base class(es) so we can tell you if your class is serializable or not.
Most cases where changes to ScriptableObjects are not serialized is the wrong usage. ScriptableObjects are mainly meant to be stored as standalone assets in your project. If they should be referenced by prefabs you have to store them as asset. Creating an asset of a scriptable object is very easy nowadays. You can simple add the CreateAssetMenuAttribute attribute to the class(es) that you want to be able to create an instance of and you can simply create them from the Create menu in Unity.
Also, i'm not sure how Sprite is coded, but in case of auto-serialization, fields of non-serializable types will be ingored. Even if marked for serialization.
The Sprite class is derived from UnityEngine.Object and therefore a serializable reference given the sprite referenced is an asset in the project and not a dynamical created object.
I added the Character.cs file to my original post. The Character class is abstract, thus not serializable. I figured if I were to hide the non-serializable field from the abstract class, I could make a serializable version for the child class. I simply want to be able to select a sprite from the editor window. That is my entire goal.
EDIT: I'd also like to note that I meant that I scrapped the entire scriptable object idea to make these custom classes.
As i said, this is not possible. Have you read the documentaion link about script serialization? Custom serializable classes act like structs and do not support polymorphism. Such classes are serialized inline based on the field type. So if you have a field or array of type Character Unity will actually serialize Characters, no matter which subclass you actually store in that variable.
If you want to be able to use polymorphism you have to derive your Character class from ScriptableObject and store the instances as assets.
I went back to scriptable objects and made it work really easily the second time around. I have now read through the documentation and related documentation. It seems that Unity program$$anonymous$$g is a bit of an adjustment. Thank you for your patience and guidance!
Answer by madks13 · Jul 30, 2018 at 09:14 AM
Properties are not shown in the Editor. Use fields. If you need, you can leave properties for access from other classes and use private fields to show in the Editor. Use [SerializeField] to show private fields in the Editor.
Edit : In order to add code formatting to text, you need to place 4 spaces at the begining of the line. If you are doing it manually.
The field I am trying to serialize is the Sprite at the top of the file. That is why it is not a property. Did I do it incorrectly?
Your answer
Follow this Question
Related Questions
CustomEditor for a list of polymorphic items 2 Answers
UnityEvent Serialization Problem 1 Answer
unity doesn't recognize the derived class 3 Answers
Copy reference from one component to another derived component., 2 Answers
Editing prefab fields from custom editor that are not automatically serialized 0 Answers