ES3.Save() does not save classes that have been inherited multiple times

Discussion and help for Easy Save 3, The Complete Save Game & Data Serializer System for the Unity Engine
Post Reply
ank111
Posts: 2
Joined: Thu Oct 31, 2024 2:13 pm

ES3.Save() does not save classes that have been inherited multiple times

Post by ank111 »

I wrote a save system for my quiz game. I decided to make a nested dictionary as Category -> Level -> Question list. Since nested dictionary would look bad (Dictionary<key,Dictionary<key,...>>), I wrote a built-in dictionary class. I created CategoryData, LevelData and QuestionData classes inherited from this class. When the record exists, I reloaded the data with the Load() method. When the record doesn't exist, I filled the data with the initial values ​​and then saved it. At the first launch, the data is filled with the initial values, the game works normally, but at the next launch, the record disappears. To prove this, I converted the data to a byte array and checked the length of the array (Pic1). However, when I converted the class to a byte array and saved it, then loaded it back as a byte array and converted it to CategoryData type, the data was not lost (Pic2). Is there a better solution?

Quiz Data class:

Code: Select all

    class QuizData
    {
        private CategoryData _data;

        private void Save()
        {
            ES3.Save("QuizData", _data);
            Debug.Log("Saved Bytes: " + _data.Serialize().Length);
        }
        private void Load()
        {
            _data = ES3.Load<CategoryData>("QuizData");
            Debug.Log("Loaded Bytes: " +_data.Serialize().Length);
        }

        [Serializable]
        private class CategoryData : BuiltInDictionary<string, LevelData> { }
        [Serializable]
        private class LevelData : BuiltInDictionary<int, QuestionData> { }
        [Serializable]
        private class QuestionData
        {
            public void SetSolved()
            {
                Solved = true;
            }
            public bool Solved { get; internal set; }
        }
        
Built-in dictionary:

Code: Select all

    [Serializable]
    public class BuiltInDictionary<TKey, TValue>
    {
        public Dictionary<TKey, TValue> Dictionary { get; } = new Dictionary<TKey, TValue>();
        public void AddToDictionary(TKey key, TValue value)
        {
            Dictionary[key] = value;
        }
    }
Serializer extension:

Code: Select all

	public static byte[] Serialize(this object obj)
        {
            if (obj == null)
                return null;

            BinaryFormatter bf = new BinaryFormatter();
            using (MemoryStream ms = new MemoryStream())
            {
                bf.Serialize(ms, obj);
                return ms.ToArray();
            }
        }

        public static T Deserialize<T>(this byte[] byteArray)
        {
            if (byteArray == null || byteArray.Length == 0)
                return default;

            BinaryFormatter bf = new BinaryFormatter();
            using (MemoryStream ms = new MemoryStream(byteArray))
            {
                return (T)bf.Deserialize(ms);
            }
        }
Byte array save & load:

Code: Select all

	private void Save()
        {
            Debug.Log("Saved Bytes: " + _data.Serialize());
            ES3.Save("QuizData", _data.Serialize());
        }
        private void Load()
        {
            _data = ES3.Load<byte[]>("QuizData").Deserialize<CategoryData>();
            Debug.Log("Loaded Bytes: " +_data.Serialize().Length);
        }
Pic1: Image
Pic2: Image
User avatar
Joel
Moodkie Staff
Posts: 5037
Joined: Wed Nov 07, 2012 10:32 pm

Re: ES3.Save() does not save classes that have been inherited multiple times

Post by Joel »

Hi there,

This is because we follow Unity's specification for what gets serialized (not .NETs), so properties need to be marked with [SerializedField] or [ES3Serializable] and have a getter and setter to be serialized.

For more info please see the Supported Types guide:
https://docs.moodkie.com/easy-save-3/es ... ted-types/

For example, this code works:

Code: Select all

using System;
using System.Collections.Generic;
using UnityEngine;

public class ank111test : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        var questionData = new QuestionData();
        questionData.SetSolved();

        var levelData = new LevelData();
        levelData.Dictionary.Add(1, questionData);

        var categoryData = new CategoryData();
        categoryData.Dictionary.Add("key", levelData);
        ES3.Save("data", categoryData);
        var loaded = ES3.Load<CategoryData>("data");

        Debug.Assert(loaded.Dictionary["key"].Dictionary[1].Solved == true);
    }
}

class CategoryData : BuiltInDictionary<string, LevelData> { }
class LevelData : BuiltInDictionary<int, QuestionData> { }
class QuestionData
{
    public void SetSolved()
    {
        Solved = true;
    }

    [SerializeField]
    public bool Solved { get; internal set; }
}

[Serializable]
public class BuiltInDictionary<TKey, TValue>
{
    [SerializeField]
    public Dictionary<TKey, TValue> Dictionary { get; set; } = new Dictionary<TKey, TValue>();
    public void AddToDictionary(TKey key, TValue value)
    {
        Dictionary[key] = value;
    }
}
All the best,
Joel
Joel @ Moodkie Interactive
Purchase Easy Save | Contact | Guides | Docs | Getting started
ank111
Posts: 2
Joined: Thu Oct 31, 2024 2:13 pm

Re: ES3.Save() does not save classes that have been inherited multiple times

Post by ank111 »

Thank you for your support. Problem is solved.
Post Reply