Domain reload is the code reload mechanism used by the Mono scripting backend. For more information on when the Unity Editor performs code reload and how your code can hook into that process via callbacks, refer to Code reload and the code lifecycle.
By default the Editor performs domain reload on entering Play mode to reset the application state. Resetting state before entering Play mode is often desirable so your application starts up as it would at the beginning of a new build. For example, static counters that were incremented in a previous Play mode session should begin from zero again in the next one.
However, domain reload is also a time-consuming operation that negatively impacts iteration times when you frequently switch between Edit and Play mode. For faster iteration times, you can turn domain reload off on entering Play mode but you must then reset static state in some other way.
When you turn domain reload off:
OnDisable or OnEnable calls for 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[ExecuteInEditMode] or [ExecuteAlways].To compensate for this persistence of data between Play mode sessions and enter Play mode with a fresh application state, you must reset state in your code.
For more information on the effects of disabling domain and sceneA Scene contains the environments and menus of your game. Think of each unique Scene file as a unique level. In each Scene, you place your environments, obstacles, and decorations, essentially designing and building your game in pieces. More info
See in Glossary reload, refer to Domain and scene reload execution order reference.
When domain reloading is off, the values of static fields and the handlers assigned to static events persist between Play mode runs. The following code example has a static counter that increments on a press of any keyboard key.
With domain reload on, Unity reinitializes this code on entering Play mode, erasing the state from the previous Play mode run, including the counter value. With domain reload off, the counter value is preserved from the previous run. On the next run of Play mode, the counter begins with the value it had at the end of the previous run.
// Copy-paste this code into a MonoBehaviour script attached to a GameObject in your project.
// Run it with domain reload enabled and then with domain reload disabled and note the different behavior.
using UnityEngine;
public class StaticsReset : MonoBehaviour
{
// With domain reload disabled this counter won't reset to zero on exiting Play mode
static int counter = 0;
void Update()
{
if (Input.anyKeyDown)
{
counter++;
Debug.Log("Counter: " + counter);
}
}
}
You can fix the problem behavior with code that explicitly resets the counter between Play mode runs. You can either do this manually by writing code to reset the counter on entry to or exit from Play mode, or you can use the static cleanup attributes to have this done for you automatically on entry to Play mode.
You can manually reset static state on entry to or exit from Play mode using the lifecycle attributes [OnEnteringPlayMode] and [OnExitingPlayMode] respectively. It’s often most efficient to reset state on exiting Play mode rather than on entering. The following example resets a static counter on exiting Play mode:
using UnityEngine;
public class ManualStaticsReset : MonoBehaviour
{
static int counter = 0;
public static void ResetCounter() => counter = 0;
// Update is called once per frame
void Update()
{
if (Input.anyKeyDown)
{
counter++;
Debug.Log("Counter: " + counter);
}
}
}
public static partial class PlayModeManager
{
[OnEnteringPlayMode]
static void Init()
{
Debug.Log("Entering Play mode!");
}
[OnExitingPlayMode]
private static void OnExitPlayMode()
{
Debug.Log("Resetting counter.");
// Reset the counter so it starts from 0 on the next Play mode run
ManualStaticsReset.ResetCounter();
Debug.Log("Exiting Play mode!");
}
}
If your code executes in Edit mode in addition to Play mode, you can’t rely on resetting state on exiting Play mode. Your code might modify a static variable while in Edit mode, so you must reset the variable on entering Play mode instead.
Note: For scripts that execute in Edit mode, disabling domain reload skips MonoBehaviour.OnDisable and disabling scene reload skips MonoBehaviour.OnDestroy, which makes these methods inappropriate for resetting state in such scripts. For more information, refer to Details of disabling domain and scene reload.
The [AutoStaticsCleanup] and [NoAutoStaticsCleanup] attributes use code generation to reset static state automatically on entering Play mode. You can apply them to static fields to specify that the field should or should not be automatically reset on entering Play mode.
The following example shows how to use these attributes:
using Unity.Scripting.LifecycleManagement;
using UnityEngine;
public partial class AutomaticStaticsReset : MonoBehaviour
{
[AutoStaticsCleanup]
public static int cleanedUpCounter = 0;
[NoAutoStaticsCleanup]
public static int counter = 0;
void Start()
{
Debug.Log(cleanedUpCounter); // Counter value is reset each time entering Play Mode
Debug.Log(counter); // Counter value is only reset on Domain Reload
cleanedUpCounter++;
counter++;
}
}
Automatic statics cleanup is supported by code generation and a code analyzer. When you apply [AutoStaticsCleanup] and [NoAutoStaticsCleanup] to your code, the code generator generates the necessary cleanup code.
Code generation for the static cleanup attributes is on by default. If you don’t want to use these attributes and prefer to write your own cleanup code instead, you can turn code generation off with a global config file.
The autostatics cleanup code analyzer analyzes the code in your assembly to provide guidance on which static variables need to be reset and how. This is especially useful when you have domain reload off and aren’t using the static cleanup attributes, as it helps you identify which static variables need to be reset manually. Code analysis for the static cleanup attributes is off by default. You can turn it on with a global config file.
You can configure code generation and code analysis settings per assembly using a .globalconfig file alongside the assembly. To configure these settings, do as follows:
<assemblyDefinitionName>.globalconfig file in the same folder..globalconfig file:| Property | Description |
|---|---|
is_global |
Marks this file as an analyzer config file. Can be omitted, but if present this property must be set to true. The default value is true. |
build_property.UnityEnableAutoStaticsCleanupCodeGen |
Enables code generation for automatic statics cleanup. This must be set to true to use the [AutoStaticsCleanup] and [NoAutoStaticsCleanup] attributes. The default value is true. |
build_property.UnityEnableLongAutoStaticsCleanupUsageAnalysis |
Enables code analysis for automatic statics cleanup. The analyzer analyzes the code for static variables in your assembly that need resetting and provides information on how to do so. The default value is false. |
The following is an example of a .globalconfig file with a configuration that corresponds to the default settings:
is_global = true // enables Roslyn
build_property.UnityEnableAutoStaticsCleanupCodeGen = true // statics cleanup code generator on
build_property.UnityEnableLongAutoStaticsCleanupUsageAnalysis = false // statics cleanup analyzer off
Important: .globalconfig files must be placed in subfolders under the Assets folder. If you’re happy with the default configuration of code generation on and code analysis off, you don’t need to create this file and can simply begin using the static cleanup attributes in your code.