Play Mode is at the core of what makes Unity fun to work with. But as your projects get more complex, it can take a while to get started. The faster you can enter and exit Play Mode, the faster you can make and test changes. That’s why we’re introducing Configurable Enter Play Mode in Unity 2019.3 beta as an experimental feature.

Currently, when you enter Play Mode in the Editor, Unity does two things: it resets the scripting states (Domain Reload) and reloads the Scene. This takes time, and the more complex your project gets, the longer you need to wait to test out new changes in Play Mode. Starting with Unity 2019.3 beta, however, you’ll have an option to disable either, or both, of the “Domain Reload” and “Scene Reload” actions.

Based on our test results, this can save you up to 50-90% of waiting time, depending on your project.

When you enable Enter Play Mode Options in File > Project Settings > Editor, you’ll see that the options to reload Domain and reload Scene become available. Check out How to configure Play Mode in the documentation for more details.

These options allow you to disable Domain and/or Scene reloading from the Enter Play Mode process when there are no code changes. You can also access this feature through an API and a Callback if you want to reset the game state before entering Play Mode.

The diagram below shows the Enter Play Mode process before and after you disable Reload Domain and Reload Scene:

See more details on the processes that Unity goes through when entering Play Mode in the documentation.

Note that this feature is currently experimental and not all Unity packages are validated to work with disabled Domain and Scene Reloading. Please let us know on the forum if you run into any issues!

How to modify your scripts correctly when you’ve disabled Domain Reload

As you can see, avoiding Domain reload is very simple, but it comes at a cost. You need to make adjustments to static fields and static event handlers in your scripts to ensure your scripting states reset correctly when Play Mode is entered.

The following code example has a counter which goes up when the player presses the Jump button. When Domain Reloading is enabled, the counter automatically resets to zero when entering Play Mode. After you disable Domain Reloading, the counter doesn’t reset; it keeps its value in and out of Play Mode. This means that on the second run of your Project in the Editor, the counter might not be at zero if it changed in the previous run.

public class StaticCounterExample : MonoBehaviour { //this counter will not reset to zero when Domain Reloading is disabled static int counter = 0; // Update is called once per frame void Update() { if (Input.GetButtonDown("Jump")) { counter++; Debug.Log("Counter: " + counter); } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public class StaticCounterExample : MonoBehaviour { //this counter will not reset to zero when Domain Reloading is disabled static int counter = 0 ; // Update is called once per frame void Update ( ) { if ( Input . GetButtonDown ( "Jump" ) ) { counter ++ ; Debug . Log ( "Counter: " + counter ) ; } } }

Use the [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)] attribute, and reset the value explicitly to make sure the counter resets correctly when Domain Reloading is disabled. Example:

using UnityEngine; public class StaticCounterExampleFixed : MonoBehaviour { static int counter = 0; [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)] static void Init() { Debug.Log("Counter reset."); counter = 0; } // Update is called once per frame void Update() { if (Input.GetButtonDown("Jump")) { counter++; Debug.Log("Counter: " + counter); } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 using UnityEngine ; public class StaticCounterExampleFixed : MonoBehaviour { static int counter = 0 ; [ RuntimeInitializeOnLoadMethod ( RuntimeInitializeLoadType . SubsystemRegistration ) ] static void Init ( ) { Debug . Log ( "Counter reset." ) ; counter = 0 ; } // Update is called once per frame void Update ( ) { if ( Input . GetButtonDown ( "Jump" ) ) { counter ++ ; Debug . Log ( "Counter: " + counter ) ; } } }

After you’ve disabled Domain Reloading, Unity won’t unregister methods from static event handlers when you exit Play Mode. This can lead to complications if you have code that registers methods with static event handlers. For example, on the first Play of your project in the Editor, methods would be registered as normal. However, on the second Play of your project, those methods would be registered a second time in addition to the first, and would, therefore, be called twice when the event occurs.

The following code registers a method with the static event handler Application.quitting:

using UnityEngine; public class StaticEventExample : MonoBehaviour { void Start() { Debug.Log("Registering quit function"); Application.quitting += Quit; } static void Quit() { Debug.Log("Quitting!"); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 using UnityEngine ; public class StaticEventExample : MonoBehaviour { void Start ( ) { Debug . Log ( "Registering quit function" ) ; Application . quitting += Quit ; } static void Quit ( ) { Debug . Log ( "Quitting!" ) ; } }

When Domain Reloading is disabled, the above example adds the Quit method again each time you enter Play Mode. This results in an additional “Quitting” message each time you exit Play Mode.

Use the [RuntimeInitializeOnLoadMethod] attribute, and unregister the method explicitly so that it isn’t added twice:

using UnityEngine; public class StaticEventExampleFixed : MonoBehaviour { [RuntimeInitializeOnLoadMethod] static void RunOnStart() { Debug.Log("Unregistering quit function"); Application.quitting -= Quit; } void Start() { Debug.Log("Registering quit function"); Application.quitting += Quit; } static void Quit() { Debug.Log("Quitting the Player"); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 using UnityEngine ; public class StaticEventExampleFixed : MonoBehaviour { [ RuntimeInitializeOnLoadMethod ] static void RunOnStart ( ) { Debug . Log ( "Unregistering quit function" ) ; Application . quitting -= Quit ; } void Start ( ) { Debug . Log ( "Registering quit function" ) ; Application . quitting += Quit ; } static void Quit ( ) { Debug . Log ( "Quitting the Player" ) ; } }

See more details on modifying your scripts to perform correctly when Domain Reload is disabled in our documentation.

Asset Store

We would like to make sure that popular Asset Store packages work with disabled Domain and Scene Reloading. You can help us by reporting any problems you encounter in your projects to the publishers of your asset packages.

Join Unity 2019.3 beta!

We believe that if your project is currently slow to enter Play Mode, this feature will speed things up significantly. Join Unity 2019.3 beta and try it out, we’re looking forward to hearing what you think on the forum! Since this feature is experimental, you can still help us shape it so that it fits your needs. We’re especially looking forward to hearing about any issues that you come across.

Huge thanks to forum users @Sini, @chrisk, @Peter77, and @Baste who have already helped the whole community out by testing this feature and providing invaluable feedback.