In this lesson, you will learn how to use ISerializationCallbackReceiver to manually process data that Unity’s default serialization system cannot handle on its own.
The Serialization Challenge
Unity automatically saves and loads data for your scripts based on specific rules: it handles public variables and those marked with [SerializeField]. However, some data types—like Dictionary<TKey, TValue> or complex class structures—are not natively serializable. If you try to save these in the Inspector or across a scene reload, the data simply vanishes.
Bridging the Gap
The ISerializationCallbackReceiver interface allows you to step into the "before" and "after" of the serialization process. It provides two methods:
OnBeforeSerialize(): Triggered right before Unity saves your data. This is where you convert your complex, non-serializable data (like a Dictionary) into a format Unity can read, such as two separateListarrays (keys and values).OnAfterDeserialize(): Triggered right after Unity loads your data. This is where you take those simple lists and reconstruct your complex data structure back into a usableDictionary.
Implementation Example
Here is how you would bridge a Dictionary so it survives a scene save:
using System.Collections.Generic;
using UnityEngine;
public class InventoryManager : MonoBehaviour, ISerializationCallbackReceiver
{
public Dictionary<string, int> inventory = new Dictionary<string, int>();
[SerializeField] private List<string> keys = new List<string>();
[SerializeField] private List<int> values = new List<int>();
public void OnBeforeSerialize()
{
keys.Clear();
values.Clear();
foreach (var kvp in inventory)
{
keys.Add(kvp.Key);
values.Add(kvp.Value);
}
}
public void OnAfterDeserialize()
{
inventory.Clear();
for (int i = 0; i < keys.Count; i++)
inventory[keys[i]] = values[i];
}
}
By using these callbacks, you keep your code clean while ensuring that complex logic remains consistent across the Unity serialization lifecycle. You aren't forced to change your runtime data structures just to satisfy Unity’s storage constraints; instead, you provide a "translator" that runs automatically in the background.
Key Takeaway: Use ISerializationCallbackReceiver to bridge the gap between complex runtime data structures and Unity's rigid serialization rules by manually packing and unpacking data.