[SerializeField] What Does Unity Actually Serialize?
Minh Khoa
Author
Short answer:
[SerializeField]lets Unity save a fieldprivateand display it in the Inspector. However, the field’s data type still must be supported by Unity.

What is Serialization?
While the game is running, an object’s data is in RAM:
Enemy
├── maxHealth: 100
├── moveSpeed: 4
└── weapon: Sword.asset
When saving a Scene, Prefab, or Asset, Unity needs to convert this state into storable data.
Object trong RAM
↓ Serialize
Dữ liệu trong Scene, Prefab hoặc Asset
↓ Deserialize
Object được dựng lại
Concepts to distinguish:
| Concept | Meaning |
|---|---|
| Serialization | Converting an object’s state into storable data |
| Deserialization | Reading data and reconstructing the object’s state |
| Serializer | The system that performs the two processes above |
| Serialized field | A field that Unity includes in the data to be saved |
| Runtime data | Data that exists only in the current play session |
Unity serializes data, not the logic inside methods:
public class Enemy : MonoBehaviour
{
[SerializeField] private int maxHealth = 100;
public void TakeDamage(int damage)
{
// Nội dung method này không được serialize
}
}
Unity saves the value maxHealth, but does not save the code inside TakeDamage().
Attributes that are easy to confuse
| Attribute | Purpose |
|---|---|
[SerializeField] | Allows Unity to serialize a field private |
[System.Serializable] | Allows a custom class or struct to be serialized by Unity |
[SerializeReference] | Serialize custom C# object by reference, supporting polymorphism and null |
[System.NonSerialized] | Does not allow Unity to serialize a field |
[HideInInspector] | The field is still serialized but hidden from the Inspector |
[FormerlySerializedAs] | Rename a field without losing old data |
[SerializeField]
[SerializeField] placed on a field:
[SerializeField] private int maxHealth = 100;
It is not a data type and it is not a method. It is an attribute that tells Unity:
Put this field
privateinto the serialization system.
[System.Serializable]
This attribute is placed on a custom class or struct:
[System.Serializable]
public class DropEntry
{
public ItemData item;
public float chance;
}
It indicates that the valid fields inside it DropEntry can be serialized by Unity.
These two attributes have different roles:
[SerializeField] → Đánh dấu một field
[Serializable] → Đánh dấu một class hoặc struct
When is a field serialized?
A field must satisfy all three conditions:
Public hoặc có [SerializeField]
+
Không static, const, readonly
+
Type được Unity hỗ trợ
Example:
public class Enemy : MonoBehaviour
{
public int damage; // ✅
[SerializeField] private int maxHealth; // ✅
private int currentHealth; // ❌
public static int enemyCount; // ❌
[SerializeField] private readonly int id; // ❌
}
[SerializeField] you cannot force Unity to serialize a type that is not supported.
What can Unity serialize?
Common groups include:
int,float,double,bool,string.enum.Vector2,Vector3,Quaternion,Color,Rect,AnimationCurve...- Reference to
GameObject,Transform,Material,Texture,MonoBehaviour,ScriptableObject... - Custom class or struct with
[System.Serializable]. - Array and
List<T>of valid types.
Example:
[System.Serializable]
public class DropEntry
{
[SerializeField] private ItemData item;
[SerializeField, Range(0f, 1f)] private float chance;
}
public class Enemy : MonoBehaviour
{
[SerializeField] private int maxHealth;
[SerializeField] private Transform attackPoint;
[SerializeField] private List<DropEntry> dropTable;
}
In the example above:
intis serialized.Transformis stored as a reference.DropEntryis serialized because it has[System.Serializable].List<DropEntry>is supported becauseDropEntryis a valid type.
What is not serialized directly?
| Data | Serialize? |
|---|---|
static, const, readonly | ❌ |
| Property | ❌ |
Dictionary<TKey, TValue> | ❌ |
Multidimensional arrays such as int[,] | ❌ |
Jagged arrays such as int[][] | ❌ |
Nested containers such as List<List<int>> | ❌ |
Delegate, event, Action | ❌ |
The following example still does not work:
[SerializeField]
private Dictionary<string, int> inventory;
[SerializeField] only marks the field. It does not make Dictionary become a supported type.
One simple way is to convert the data into List:
[System.Serializable]
public class InventoryEntry
{
public string itemId;
public int amount;
}
[SerializeField]
private List<InventoryEntry> inventory;
If runtime needs Dictionaryit can be reconstructed from the list when initializing.
A property does not behave like a field
Unity’s serializer works directly with fields:
public int Health { get; private set; }
The property above is not serialized in the usual way.
A clearer way:
[SerializeField] private int health;
public int Health => health;
Code outside can only be read Health; meanwhile, the original value can still be configured from the Inspector.
The Inspector also does not call getters or setters. If you need to validate data when editing in the Inspector, you can use OnValidate:
private void OnValidate()
{
health = Mathf.Max(1, health);
}
When is it needed [SerializeReference]?
By default, custom C# classes are serialized by Unity by value. Use [SerializeReference] when you need:
- Save an object through a base class or interface.
- Preserve the correct derived type.
- Preserve the value
null. - Multiple fields referencing the same instance.
- Tree- or graph-shaped data.
[SerializeReference]
private BaseEffect effect;
[SerializeReference] adds overhead and is not used to fix the limitations of Dictionary. For data shared among multiple components, ScriptableObject is often a better fit.
Renaming a field can cause data loss
Suppose multiple Prefabs are storing the field:
[SerializeField] private int health;
If you rename it directly:
[SerializeField] private int maxHealth;
Unity may treat maxHealth as a new field and lose the old health value.
Safe approach:
using UnityEngine.Serialization;
[FormerlySerializedAs("health")]
[SerializeField] private int maxHealth;
Serialization is not Save Game
Unity serialization mainly serves:
- Inspector.
- Scene.
- Prefab.
- ScriptableObject and Asset.
- Instantiate.
- Hot reload in the Editor.
It does not automatically save the player's progress.
Runtime State
↓
SaveData
↓
JSON hoặc Binary
↓
Application.persistentDataPath
Current HP, inventory, and quests still need a separate Save/Load system.
How to remember
Serialization = Object → Data
Deserialization = Data → Object
[SerializeField] = Cho phép serialize một field private
[Serializable] = Cho phép serialize custom class hoặc struct
And the most important sentence:
[SerializeField]only fields participate in the serialization system. Whether a field is saved still depends on the modifier and the underlying data type.