Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Problems about ISerializationCallbackReceiver In Unity Script API

I am learning something about Serialization in Unity, and know that ISerializationCallbackReceiver can be used to help serialize some complex data structure that cannot serialize directly. I have tested the following code in Unity 2017 and Find some problems.

public class SerializationCallbackScript : MonoBehaviour, ISerializationCallbackReceiver
{
    public List<int> _keys = new List<int> { 3, 4, 5 };
    public List<string> _values = new List<string> { "I", "Love", "Unity" };

    //Unity doesn't know how to serialize a Dictionary
    public Dictionary<int, string>  _myDictionary = new Dictionary<int, string>();

    public void OnBeforeSerialize()
    {
        _keys.Clear();
        _values.Clear();

        foreach (var kvp in _myDictionary)
        {
            _keys.Add(kvp.Key);
            _values.Add(kvp.Value);
        }
    }

    public void OnAfterDeserialize()
    {
        _myDictionary = new Dictionary<int, string>();

        for (int i = 0; i != Math.Min(_keys.Count, _values.Count); i++)
            _myDictionary.Add(_keys[i], _values[i]);
    }

    void OnGUI()
    {
        foreach (var kvp in _myDictionary)
            GUILayout.Label("Key: " + kvp.Key + " value: " + kvp.Value);
    }
}

Obviously, this example show me how to serialize a dictionary by changing it into a list and resuming when deserialize. However, when i run the codes pratically, I find _keys and _values both empty (keys.Count = 0) in inspector. Even worse, i cannot modify their values in the inspector. As a result, nothing appears when entering the play mode.

So I want to know what is the actual usage of ISerializationCallbackReceiver and the reason of what happened.

like image 669
Luren Wang Avatar asked Jun 23 '26 10:06

Luren Wang


1 Answers

OnBeforeSerialize is called in the editor every time the inspector updates (basically always), and it calls clear on your keys and value lists

i changed this for me like that:

#if UNITY_EDITOR
using UnityEditor;    
#endif

public class ....{

    public void OnBeforeSerialize() {
#if UNITY_EDITOR
        if(!EditorApplication.isPlaying
        && !EditorApplication.isUpdating
        && !EditorApplication.isCompiling) return;
#endif
        ...

so it does not clear on edit-time.

like image 60
Soraphis Avatar answered Jun 26 '26 16:06

Soraphis