SerializeField in Unity

May 26, 2023

On this page

    What you will learn

    In this article, I will break down everything that you need to know about the SerializeField attribute in Unity.

    By the end of this article, you will know what the SerializeField attribute does, you will understand what types of fields are serializable, and you will feel comfortable deciding when and where to use it in your own code.

    You will also learn about [.c][System.NonSerialized][.c] and [.c][field:SerializeField][.c] attributes.

    TL;DR

    Always use private fields and variables in your classes.

    If you want Unity to show a field in the inspector, use the SerializeField attribute, [.c][SerializeField][.c].

    You use the SerializeField attribute like this:

    [.c][SerializeField] private int MaximumHealth;[.c]

    What does SerializeField do?

    In this section, I will describe what the SerializeField attribute actually does in Unity. 

    If you understand what Serialization means in Unity, it is straightforward. If you don’t understand what Serialization means in Unity, then you’ll want to read this section, read the next section, then read this section again.

    So, without further ado:

    SerializeField forces Unity to serialize a field.

    That’s it. Kind of. On its own, this is… fine. However, this attribute is mostly helpful because of the following characteristics:

    You want to see and edit private values.... but don't want the values saved? So when you edit it, the changed value just....vanishes into the ether? Why is it important that the values not be serialized to disk? And if that is important, then what is the point of editing them if they'll just disappear?

    • Unity wants to draw all the fields in the class in the Inspector.
    • But, it can only draw fields that are serialized on the disk.
    • When you serialize the field, Unity has a copy on the disk that it can use to draw the field in the inspector.
    • When you change the value in the inspector, you are changing the serialized object.
    • Therefore, you must use SerializeField to enable Unity to draw an editable field in the Inspector.

    In the next section, I’ll break down what Serialization means in Unity, offer an analogy, and a couple of examples.

    What does Serialization mean in Unity?

    In this section, I’ll break down what it actually means to serialize a field in Unity. I will explain how serialization impacts your project. Then, I will give an example of a serialized field, an implicitly serialized field, and a non-serialized field to illustrate how they work differently..

    What is Serialization in Unity?

    Other tutorials skip this topic. This tutorial will not skip this topic. It is important that you understand what Serialization actually is and how it actually applies in your project.

    Serialization refers to a process wherein Unity extracts variable data from your class. Unity wants to extract this variable data so that when Unity reloads that class, it can put the variable data back where it was. 

    Time for an analogy. Imagine you are a sneaky little thief. Assume that you have broken into someone’s house to find an important document. You don’t know where the document is, so you will need to dig around. You don’t want this person to know that you broke in, so you need to put everything back where you found it before you leave. As a reasonable person, you might take a few minutes to record (a.k.a Serialize) the state of the home so that you can make sure you put it back where it was when you entered.

    When you reload your domain in Unity, Unity records (serializes) the state of your house (your scripts), bulldozes the entire house (your scripts), then recreates the house (your scripts) based on the record (serialized version).

    One scenario where a script reload happens is when you edit a script, save the script, then return to the Unity Editor. Boom: Hot Reload.

    Listen up, this is important:

    During Hot Reload, Unity will always serialize fields that are capable of being serialized, even if it is a private field that is not marked with [SerializeField]. These fields are Implicitly Serialized.

    You can specifically override this behavior by marking the field as [System.NonSerialized].

    Confused? Of course you are. I made a small example that you can import to your project. Follow along for fun.

    In this example, we have three fields.

    [.c][SerializeField] private string mySerializedField = "My Serialized Field";[.c]

    [.c]private string myImplicitSerializedField = "My Implicit Serialized Field";[.c]

    [.c][System.NonSerialized] private string myNonSerializedField = "My Non-Serialized Field";[.c]

    This script will run in the editor. 

    The Console logs the value of the three fields:

    • “My Serialized Field”
    • “My Implicit Serialized Field”
    • “My Non-Serialized Field”

    We’re going to wait five seconds, then we’re going to change the value of each of these three fields. 

    The console logs the three fields.

    • “My Updated Serialized Field”
    • “My Updated Implicit Serialized Field”
    • “My Updated Non-Serialized Field”

    Now we will force a hot reload: Open the script, change something small, save it, and go back to Unity.

    The console logs the three fields.

    • “My Updated Serialized Field”
    • “My Updated Implicit Serialized Field”
    • My Non-Serialized Field

    Huh? What’s that?

    Unity correctly recorded and restored our SerializedField and implicitly SerializedField.

    But, Unity did not put back our NonSerialized Field.

    Unity normally tries to record each of the serializable fields in the class before the Hot Reload. However, we marked one field as NonSerialized. This attribute forced Unity to ignore the NonSerialized field when it recorded the class variables before the Hot Reload. 

    When Unity reloaded the script, the variable is reset to the value written in the declaration:

    [.c]myNonSerializedField = “My Non-Serialized Field”[.c]. 

    Normally, it would restore the field to the serialized value. But in this case, the value is NonSerialized. Unity did not record a value before the Hot Reload. Therefore, it has nothing to restore to the value now that the Hot Reload is over.

    Does Unity save Serialized Fields between Editor sessions?

    Yes.

    If you modify a Serialized Field in the Inspector, Unity will save that value. If you close the Editor and re-open it, the Serialize Field will still have the value that you set.

    Does Unity save Serialized Fields between play sessions in the Editor?

    No.

    If your game modifies a Serialized Field during gameplay while in Play mode in the Editor, Unity will reload the serialized value when you exit play mode.

    Does Unity save Serialized Fields between play sessions in a build?

    In short, no.

    In order to save player data in between sessions, you do need to Serialize the data and save it on disk. To load that data later, you need to find the literal file that you saved that data to and then deserialize it and load it back to your game. 

    Unity never does this automatically for you. Except in PlayerPrefs. We will cover saving and loading in Unity as well as using PlayerPrefs in a separate tutorial.

    What types of fields are Serializable?

    In general, most types are serializable.

    However, you will 100% run into a field that Unity cannot serialize on its own. So, this section will give you an idea of which fields are serializable so that you are less surprised when you get stuck later.

    General Rules

    In general, Unity is capable of serializing any instanced fields.

    • Unity is able to serialize any field except for static, const, or readonly fields.
    • Public fields are serialized by default.
    • Private fields are serialized if you use [SerializeField].

    Properties are methods that wrap fields, so they can’t be serialized. You can serialize the backing value, though. More on that later.

    Serializable Field Types

    Unity will serialize basically any primitive data type, any enum (which is basically a wrapper around the int type), any UnityEngine.Object, most Unity structs, any serializable class (e.g., any class that inherits from UnityEngine.Object), any serializable struct (e.g., many Unity structs), and any one-dimensional collection that is made up of a serializable type.

    Unity will not serialize any multidimensional collections. Multidimensional collections include things like dictionaries or multidimensional arrays.

    Click here to check the Unity docs for more details.

    Serialize the Backing Field of a Property

    If you’re unfamiliar with properties, skip this section.

    You can serialize the backing field for a property using an attribute, [field:SerializeField].

    For example:

    [.c][field: SerializeField] public string MyProperty { get; private set }[.c]

    Unity will expose the backing field in the Inspector. Any changes that you make are made directly to the backing field itself. You may have validation logic in the setter. Your change will not go through the setter, so it will not go through that verification logic. Unity simply modifies the backing field itself and completely ignores the property.

    The NonSerialized attribute can also be applied to properties. You can force Unity to discard the value during a Hot Reload by using the NonSerialized attribute on the backing field just like you would with a normal field.

    [.c][field: System.NonSerialized] public string MyNonSerializedProperty { get; private set; }[.c]

    When should I use SerializeField?

    If you want Unity to show the field in the Inspector, then use [SerializeField].

    When should I use [System.NonSerialized]

    If you want Unity to discard the field value and reset to the declaration value during a Hot Reload, then use the [System.NonSerialized] attribute.

    What is this [field: SerializeField] stuff about?

    If you want Unity to Serialize the backing field for a property, you can use the [field: SerializeField] attribute to set the attribute directly on the backing field. Ditto with [field: System.NonSerialized].

    How do Static fields work?

    Unity never restores static fields. Static fields will always be discarded during the reload process. Never use static fields for states that you need to retain between reloads.

    How do Constant fields work?

    Constant fields never change from the declaration value, so the value for the constant field will always be the same before and after reloads. You do not need to serialize a constant field because the field will never change. Ditto for fields declared readonly.

    SerializeField vs. Public

    Unity will also serialize a public field and expose it in the inspector. So, why use SerializeField instead of public?

    Well, these are two entirely separate considerations.

    [SerializeField] and [System.NonSerialized] are used to describe how Unity should treat the field with respect to Serialization.

    Public, private, and other access modifiers are used to control how other classes are able to access fields in the class in question.

    If you make a field public, it is a billboard to other developers (including you in the future). The billboard says: “Please set my value from another class”.

    Now, imagine that this field is your player’s health. 

    Do you want to have a billboard next to your player’s health that says “Please change me”? Probably not.

    If you use the [SerializeField] attribute with a private access modifier instead, you have taken down the billboard and replaced it with strong guardrails. Other classes cannot access this field. These guardrails will help protect you from funky bugs.

    Remember: you want to write code that is difficult to use incorrectly.

    A helpful rule

    Decide the two questions of access and serialization separately:

    Decide on the access modifier based on the access you want to provide to other classes.

    Decide on the Serialization attribute based on whether you want the field to be serialized, implicitly serialized, or non-serialized.

    Recommended Reading & Next Steps

    I recommend reviewing the Unity docs on SerializeField: https://docs.unity3d.com/ScriptReference/SerializeField.html

    Then, review Unity’s docs on Script Serialization: https://docs.unity3d.com/Manual/script-Serialization.html

    Then, take a look at Unity’s docs on Serialization Callbacks:

    https://docs.unity3d.com/ScriptReference/ISerializationCallbackReceiver.html

    Finally, give yourself some practice using [SerializeField], [System.NonSerialized], and try to get comfortable using private as your default access modifier. 

    (P.S. private is the default access modifier in Unity).

    Wrappin’ up

    Thanks for reading my tutorial on SerializeField in Unity! It took quite a while to research, write, and review.

    At the beginning of this article, I promised that you would know what [SerializeField] does, which fields are serializable in Unity, and that you would feel comfortable using [SerializeField] in your projects going forward. I also promised that you would learn about [System.NonSerialized] and [field:SerializeField]. 

    I certainly covered each of these topics, and I hope that I fulfilled my promise to you.

    If you have any further questions, join the OccaSoftware Discord channel for game developers.

    Michael Sacco
    Founder & CEO

    Michael Sacco is the Founder and CEO of OccaSoftware where he specializes in developing game assets for Unity game developers. With a background ranging from startups to American Express, he's been building great products for more than 10 years.

    Tags:
    programming
    resources

    Recommended Articles