Apply the following coding practices and organizational principles to prevent errors and optimize serialization performance in your project.
Most Unity APIs can only be called from the main thread. Don’t call Unity APIs from constructors and field initializers of serializable types because these run on a separate loading thread.
In development buildsA development build includes debug symbols and enables the Profiler. More info
See in Glossary, Unity throws an error if you attempt to call main thread APIs from a loading thread. In a release build, the code runs without errors but can produce crashes and other unexpected behavior in your application.
Tip: To reduce the risk of errors during serialization, don’t call API methods that can influence the project state or that involve other Unity objects. APIs that are safe to call include Debug.Log and those that work on simple data types, such as math functions and Vector3.
Don’t initiate serialization from finalizer methods. Finalizers don’t run on the main thread. The garbage collector determines when they run and in some circumstances they might not run at all.
Attempting to serialize data from a finalizer can lead to unexpected behavior and crashes. For more information, refer to the Microsoft documentation on Finalizers.
You can organize your data as follows to ensure optimal use of Unity’s serialization:
UnityEngine.Object (such as a class derived from ScriptableObject), Unity only serializes the reference and not the entire object graph. So the data is only serialized once, in the ScriptableObject, not at each point that references it. Similarly, you can use the [SerializeReference] attribute if you want to reference the same custom C# class more than once within a single MonoBehaviour or ScriptableObject. For more information, refer to Serialization of custom classes.When you change the structure of a script or a prefabAn asset type that allows you to store a GameObject complete with components and properties. The prefab acts as a template from which you can create new object instances in the scene. More info
See in Glossary, Unity doesn’t immediately rewrite every asset that already references the old structure. Existing serialized data stays on disk until the affected asset is saved again. As a result, assets can accumulate stale serialized data: fields and placeholder objects that no longer correspond to anything in the current project.
Stale data commonly appears in .unity, .prefab, and .asset files in the following ways:
[SerializeField] field from a MonoBehaviour or ScriptableObject script, any asset that previously assigned a value to that field still contains the value in its YAML data. The value is invisible at runtime because the field no longer exists in the class, but it remains on disk until the asset is saved again.Unity intentionally leaves stale data in place rather than removing it on every script or prefab change for two reasons:
.meta file (so the GUID is unchanged), references to it remain valid.To preserve data when you rename a field instead of removing it, use the [FormerlySerializedAs] attribute.
To remove stale data from a single asset, modify any property on the asset in the Editor and save it. This forces Unity to rewrite the asset using the current scriptsA piece of code that allows you to create your own Components, trigger game events, modify Component properties over time and respond to user input in any way you like. More info
See in Glossary, prefabs, and asset references, dropping any data that no longer corresponds to a field or referenced object.
To clean up stale data across many assets, call the AssetDatabase.ForceReserializeAssets method from an Editor script. The following example reserializes every asset in the project from a menu item:
using UnityEditor;
public static class StaleDataCleanup
{
[MenuItem("Tools/Reserialize All Assets")]
static void ReserializeAll()
{
AssetDatabase.ForceReserializeAssets();
}
}
Without arguments, AssetDatabase.ForceReserializeAssets reserializes every asset in the project. To reserialize a specific subset, pass a list of asset paths and an optional ForceReserializeAssetsOptions value to control whether the assets, their .meta files, or both are rewritten.
Important: AssetDatabase.ForceReserializeAssets only runs from direct user actions, such as a menu item. Unity throws an exception if you call it from a Unity callback such as OnEnable (which can run while a scene is being modified), while the Editor is in Play mode, or during a domain reload.
Reserializing many assets at once produces a large set of file changes. Coordinate with your team and your version controlA system for managing file changes. You can use Unity in conjunction with most common version control tools, including Perforce, Git, Mercurial and PlasticSCM. More info
See in Glossary system before running it across a project.