The word “serialization” isn’t necessarily a term you learn about in your first year of programming, but it refers to a very basic IT concept that every Unity dev sooner or later comes in contact with.
This article is meant for Unity beginners as a short explanation about the term, what it means in Unity, and a quick note about what the [SerializeField]
attribute does.
What is serialization?
In short: Serialization is the process of taking data and formatting it to be compatible to the destination we send it to.
Usually, this means “making it one-dimensional”. You take all the objects in your program and put them in a row so you can write them down in a continuous string that is then written into a file, or uploaded to a web server.
The inverse process of “deserialization” means taking serialized data and building the data structures (objects) from that.
What does Unity serialize?
When you work in the Unity Editor and build a scene or a prefab, you create a bunch of data that will be part of the game you make. Every scene is a file in your assets folder, and to save the positions of your terrain, your player, your enemies and everything else in that file, Unity serializes it.
Nowadays, Unity uses the text format “Yaml” for that by default. It’s a very simple format that you can actually (partially) read when you open your scene file in a text editor. In fact, it can be a valuable experience to do that once in a while to learn about how scenes work in Unity.
But for now, all we need to know that Unity serializes all GameObject
s in your scene into the scene file. And for each GameObject
, it serializes all their components. And for each component, it serializes all the properties you set in the inspector.
So as a pseudocode example, a scene file with a light in it would have a part like this:
* There's a GameObject
* It has a Transform component
* Its position is 0, 0, 0
* Its rotation is 0, 0, 0
* Its localScale is 1, 1, 1
* It has a Light component
* Its color is 1, 1, 1, 1
* Its intensity is 0.95
* ...
Whenever you save your scene, Unity writes a long text with content like this into the scene file. And whenever you load it, it reads this text and instantiates all your GameObject
s with all their components with all their properties. More or less the same happens in your game build. When the game is started, the Unity Engine reads this data from somewhere in the game files and creates your scene for you.
The same thing goes for prefabs and ScriptableObject
s.
What do I do with this?
Now that you know this, you might be reminded about your first Unity scripts, where you made a public
field in order to allow yourself or a teammate to set a value for an instance of your component.
With the serialization terminology, you know that Unity serializes all public fields in your components if it can. Some things cannot be serialized, and in those cases, nothing shows up in the inspector.
But here comes the point: The public
keyword is not something Unity invented. It’s a part of the C# programming language, and multiple languages before it. Outside of Unity, public and other keywords like it are used to specify whether other classes can access the field or method.
If the coins
field in your Purse
script is public…
public int coins;
…then other scripts can access this field and read or change the value:
var purse = GetComponent<Purse>(); purse.coins = 100;
This is not something you always want to allow, as often enough, your code requires your data to be under control of the class you write. If other classes would be able to manipulate your data in these cases, programming errors and unintended behavior of your program are more likely to happen.
So what you usually do with things that other classes shouldn’t mess around with is to not make them public, but, for example, private
.
private int coins;
Lines like
purse.coins = 100;
will produce a compilation error now and whomever wrote this line has to change it – by re-evaluating how a purse is supposed to be used.
However, in Unity, this means that the field no longer shows up in the inspector and is not serialized anymore. We lose the chance to set a value for an object that is then loaded in the game to influence its mechanics.
This is where the [SerializeField]
attribute comes in. When you put it over a non-public field, it gets serialized (and shown in the inspector) despite other classes not being able to access it.
[SerializeField] private int coins;
So we have two things we decide for each field:
- Should the field be
public
? - Should the field be serialized?
And if we assume for now that we only have public and private to work with, we have two choices for each question. This leaves us with a small matrix of ways to declare our field:
Serialized | Not Serialized | |
Public | public int coins; | [System.NonSerialized] |
Private | [SerializeField] | private int coins; |
As you can see, there’s the (not that frequent) case that you want a public field that shouldn’t be serialized. In that case, you can use [System.NonSerialized]
to disable serialization.
Conclusion
After your first steps in programming in Unity (or in general), you will notice that you have options to write your code in ways that makes mistakes in other parts of your code less likely to happen. By restricting the accessibility of your fields (and methods), for example by making them private where it makes sense, your code quality increases.
To maintain control over the serialization side effect that the public
keyword has in Unity, use the [SerializeField]
attribute on private fields to have them serialized – which means that their values get saved into your scene file and thus become part of your game.