Version: Unity 6.5 Beta (6000.5)
Language : English
Configuring how Unity enters Play mode
Enter Play mode without scene reload

Enter Play mode without domain reload

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.

Effects of turning domain reload off when entering Play mode

When you turn domain reload off:

  • Non-serialized fields keep the values assigned to them during Play mode on returning to Edit mode. This applies for fields of all script types, including MonoBehaviours (including those on prefab assets), ScriptableObjects, and your own custom C# types. For detailed information on what is and isn’t serialized in different contexts, refer to Serialization rules.
  • Static variables keep their values between Play mode sessions.
  • Static events keep their registered subscribers between Play mode sessions.
  • There are no additional 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
    See in Glossary
    marked with the [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.

Resetting state from code

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.

Manual reset of static state

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.

Automatic reset of static state

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.

Code generation and analysis configuration

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:

  1. Create an assembly definition file in your scripts folder.
  2. Create an <assemblyDefinitionName>.globalconfig file in the same folder.
  3. Turn code generation and the code analyzer on or off using the following flags in a .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.

Additional resources

Configuring how Unity enters Play mode
Enter Play mode without scene reload