Instruct Unity to serialize a field as a reference.
By default when Unity serializes an object it serializes all fields as value types, unless the field type derives from UnityEngine.Object.
Decorating a field with [SerializeReference] instructs Unity to serialize the field 'by reference' instead of 'by value'. That makes it possible to
serialize reference-based topologies, like graphs, and in the case of polymorphism the full specialized object will be serialized properly. Using SerializeReference
adds extra overhead, so it should only be used when regular 'by value' serialization is not sufficient.
The objects serialized with the SerializeReference attribute are referred to as "Managed References". The MonoBehaviour, ScriptableObject or other "host" object
that contains the [SerializeReference] fields associates a unique Id with each managed reference. This Id is typically automatically generated, but it can be specified
using SerializationUtility.SetManagedReferenceIdForObject.
Referenced objects cannot be shared between UnityEngine.Object instances. For example, two MonoBehaviours cannot share an object that is
serialized by reference. Cloning an object that hosts managed references will create a copy of all the managed reference objects.
An alternative to [SerializeReference] is to use ScriptableObject instead. ScriptableObjects have good performance and permit sharing data between MonoBehaviours.
Notes:
- The type of the object assigned to the field should be a class decorated with the Serializable attribute.
- The field value can be null.
- The field value can be be a class derived from the field type.
- The field type can be an interface, or abstract.
- The types 'System.Object', 'List<System.Object>' and 'System.Object[]' are supported for the field type.
- Neither the field type, nor the assigned object, can be of a type that specializes UnityEngine.Object.
- Field type cannot be a specific specialization of a generic type(inflated type).
- Generic Lists and array fields decorated with [SerializeReference] apply the attribute to the elements of the list/array, not the list/array instance itself.
- Fields on referenced objects cannot be animated.
See Also: SerializedProperty.managedReferenceValue, MonoBehaviour, SerializationUtility
using System; using UnityEngine;
public class SerializeReferencePolymorphismExample : MonoBehaviour { [Serializable] public class Base { public int m_Data = 1; }
[Serializable] public class Apple : Base { public string m_Description = "Ripe"; }
[Serializable] public class Orange : Base { public bool m_IsRound = true; }
// Use SerializeReference if this field needs to hold both // Apples and Oranges. Otherwise only m_Data from Base object would be serialized [SerializeReference] public Base m_Item = new Apple();
[SerializeReference] public Base m_Item2 = new Orange();
// Use by-value instead of SerializeReference, because // no polymorphism and no other field needs to share this object public Apple m_MyApple = new Apple(); }
using System; using System.Text; using UnityEngine;
public class SerializeReferenceLinkedListExample : MonoBehaviour { // This example shows a linked list structure with a single int per Node. // This would be much more efficiently represented using a List<int>, without any SerializeReference needed. // But it demonstrates an approach that can be extended for trees and other more advanced graphs
[Serializable] public class Node { // This field must use serialize reference so that serialization can store // a reference to another Node object, or null. By-value // can never properly represent this sort of self-referencing structure. [SerializeReference] public Node m_Next = null;
public int m_Data = 1; }
[SerializeReference] public Node m_Front = null;
// Points to the last node in the list. This is an // example of a having more than one field pointing to a single Node // object, which cannot be done with "by-value" serialization [SerializeReference] public Node m_End = null;
SerializeReferenceLinkedListExample() { AddEntry(1); AddEntry(3); AddEntry(9); AddEntry(81); PrintList(); }
private void AddEntry(int data) { if (m_Front == null) { m_Front = new Node() {m_Data = data}; m_End = m_Front; } else { m_End.m_Next = new Node() {m_Data = data}; m_End = m_End.m_Next; } }
private void PrintList() { var sb = new StringBuilder(); sb.Append("Link list contents: "); var position = m_Front; while (position != null) { sb.Append(" Node data " + position.m_Data).AppendLine(); position = position.m_Next; } Debug.Log(sb.ToString()); } }
using System; using System.Collections.Generic; using UnityEngine;
public interface IShape {}
[Serializable] public class Cube : IShape { public Vector3 size; }
[Serializable] public class Thing { public int weight; }
[ExecuteInEditMode] public class BuildingBlocks : MonoBehaviour { [SerializeReference] public List<IShape> inventory;
[SerializeReference] public System.Object bin;
[SerializeReference] public List<System.Object> bins;
void OnEnable() { if (inventory == null) { inventory = new List<IShape>() { new Cube() {size = new Vector3(1.0f, 1.0f, 1.0f)} }; Debug.Log("Created list"); } else Debug.Log("Read list");
if (bins == null) { // This is supported, the 'bins' serialized field is declared as a collection, with each entry as a reference. bins = new List<System.Object>() { new Cube(), new Thing() }; }
if (bin == null) { // !! DO NOT USE !! // Although, this is syntaxically correct, it is NOT supported as a valid serialization construct because the 'bin' serialized field is declared as holding a single reference type. bin = new List<System.Object>() { new Cube() }; } } }
Did you find this page useful? Please give it a rating:
Thanks for rating this page!
What kind of problem would you like to report?
Thanks for letting us know! This page has been marked for review based on your feedback.
If you have time, you can provide more information to help us fix the problem faster.
Provide more information
You've told us this page needs code samples. If you'd like to help us further, you could provide a code sample, or tell us about what kind of code sample you'd like to see:
You've told us there are code samples on this page which don't work. If you know how to fix it, or have something better we could use instead, please let us know:
You've told us there is information missing from this page. Please tell us more about what's missing:
You've told us there is incorrect information on this page. If you know what we should change to make it correct, please tell us:
You've told us this page has unclear or confusing information. Please tell us more about what you found unclear or confusing, or let us know how we could make it clearer:
You've told us there is a spelling or grammar error on this page. Please tell us what's wrong:
You've told us this page has a problem. Please tell us more about what's wrong:
Thank you for helping to make the Unity documentation better!
Your feedback has been submitted as a ticket for our documentation team to review.
We are not able to reply to every ticket submitted.