Legacy Documentation: Version 4.5.0

Script language:

  • JS
  • C#
  • Boo
Script language

Select your preferred scripting language. All code snippets will be displayed in this language.

OnBeforeSerialize(): void;
void OnBeforeSerialize();
def OnBeforeSerialize() as void

Description

Implement this method to receive a callback after unity serialized 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 INotifyOnSerialization 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 OnDeserialize 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.

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

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); } }

Using serialization callbacks to serialize a Dictionary.