Base Class And Serialization/Deserialization Of Subclasses.

I have this base class

public class SpellEffect  {

    public SpellEffect(){
    }

    public SpellEffect(string name,SpellEffectType type,float duration,float tickrate,int damage,int slowdown,int value,bool isharm)
    {
        SpellEffectName = name;
        Type = type;
        Duration = duration;
        TickRate = TickRate;
        Damage = damage;
        Slowdown = slowdown;
        EffectValue = value;
        IsHarmful = isharm;
    }

    public string SpellEffectName;

    public SpellEffectType Type;

    public float Duration;

    public float TickRate;

    public int Damage;

    public float Slowdown;

    public int EffectValue;

    public bool IsHarmful;

    public virtual void OnApply        (Mob mob)
    {    }

    public virtual void OnTick        (Mob mob)
    {    }

    public virtual void OnCrit         ()
    {    }

    public virtual void OnDispel     ()
    {    }

    public virtual void OnFinish     (Mob mob)
    {    }

}

This is how i serialize it into xml. “EffectContainer” is just a class with a list of SpellEffects.

public void CreateItem ()
    {
        EffectsContainer effectContainer = new EffectsContainer ();

        Type[] effectType = {typeof(SpellEffect)};

        FileStream fs = new FileStream (Path.Combine (Application.streamingAssetsPath, "SpellEffects.xml"), FileMode.Open);

        XmlSerializer serializer = new XmlSerializer(typeof(EffectsContainer),effectType);

        effectContainer = (EffectsContainer)serializer.Deserialize (fs);

        serializer.Serialize (fs, effectContainer);

        fs.Close ();

        effectContainer.SpellEffects.Add (new SpellEffect(SpellEffectName,Type,Duration,TickRate,Damage,Slowdown,EffectValue,IsHarmful));
           
        fs = new FileStream (Path.Combine (Application.streamingAssetsPath, "SpellEffects.xml"), FileMode.Create);
        serializer.Serialize (fs, effectContainer);
        fs.Close ();
    }

This is deserialize

    public void Awake()
    {
        Type[] itemTypes = {typeof(SpellEffect) };
        XmlSerializer serializer = new XmlSerializer (typeof(EffectsContainer), itemTypes);
        TextReader textReader = new StreamReader (Application.streamingAssetsPath + "/SpellEffects.xml");
        EffectsContainer = (EffectsContainer)serializer.Deserialize(textReader);
        textReader.Close ();
    }

My problem is, i thought i could make any subclass, lets say, damage over time spell " Burn.cs : SpellEffect "
and basically vary the OnTick() or OnDispel() Logic.
But, i am not sure how to serialize it and then deserialize into its own classes, assuming there could be n SpellEffects/Classes.

No, the XmlSerializer does not add metadata itself. So there’s no way it could distinguish which C# class should represent a value. However you can use the XmlArray and XmlArrayItem attributes like shown in this SO question. Note that you have to add an XmlArrayItem attribute for every concrete class type and give it a unique xml element name. The serializer would use that name to reconstruct the correct class based on the attribute(s).

1 Like

ok, thank you Bunny.

Btw, i went for scriptable objects, and it works even better. :d
Minor downside is, that i can’t edit SOs outside of unity, except with some crazy contraptions i guess.

You can open a scriptable object asset in any text editor and edit the data inside, should you wish to.

Alternatively, you could encapsulate your data and write some editor means to either dump out the data, or build SO’s based on your own external data.

1 Like

a) hm… when i opened it in text editors, i saw only gibberish. I had to switch to “Force Text” in Editor Serialization Options. Now i wonder, if this will affect performance or whatnot.
b) yea, that’s what i meant by crazy contraption. :smiley: