Implement this method to receive a callback before Unity serializes your object.
In contrast to many other programming environments where you often creates
objects yourself by invoking constructors, Unity will often create objects for you, and set its fields with the values that you set for them in the Editor.
The process of setting the fields of your objects, and getting them, is called deserialization and serialization respectively.
Unity's serializer is able to serialize many different kinds of fields, but not all of them.
In those cases it can be convenient to get a callback before Unity will read from your fields,
or after it has written to them, to allow you to do some custom steps. A typical use case for
this would be if you have an object graph that you know how to serialize, but Unity does not.
In that case, you can implement ISerializationCallbackReceiver interface, and before Unity will
read your fields, you manually serialize your object graph into your fields in a way that Unity
can serialize. You can do the reverse in the OnAfterDeserialize method.
The interface can be used on MonoBehaviours like in the example, but it can also be used on custom classes and structs.
This interface should be used very carefully. Unity's serializer usually runs on the non main thread,
while most of the Unity API can only be called from the main thread. Your code is also running
interleaved with Unity's serializing code, (the callbacks are not deferred), so you could seriously
confuse Unity's serializer by modifying the very objects Unity is reading from and writing to.
You're strongly recommended to only use this interface for the example use case mentioned above:
serializing something yourself that Unity doesn't know how to.
Another caveat is that serialization happens more often than you might think. When a MonoBehaviour
gets cloned through Instantiate() at runtime, it gets deserialized and serialized. If the object
had a field that pointed to its own gameObject, when that gameObject gets cloned, you'd want
the field to point to the new gameObject, not the old one. In order to update these "internal
references", Unity uses the serialization system. Unity reads all your fields, finds references
to "things that were cloned", and then writes the new values in your fields. The callbacks
will also be invoked for this updating phase, allowing you to make the updating of internal
references to also work in your custom classes that Unity cannot serialize.
Currently only classes will receive the callbacks. Structs will not.
no example available in JavaScript
using UnityEngine; using System; using System.Collections.Generic;
public class SerializationCallbackScript : MonoBehaviour, ISerializationCallbackReceiver { public List<int> _keys = new List<int>(); public List<string> _values = new List<string>();
//Unity doesn't know how to serialize a Dictionary public Dictionary<int,string> _myDictionary = new Dictionary<int,string>() { {3, "I"}, {4, "Love"}, {5, "Unity"}, }; 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(var 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 ); } }
Using serialization callbacks to serialize a Dictionary.