Digital Software Publishing Stockholm

Home › Unity tools › Guides

Which statics survive Enter Play Mode without domain reload in Unity

Why singletons, static events and counters keep stale values when domain reload is off, how to find every static in your project, and how to reset them.

2026-10-29 · Digital Software · about Static State Auditor

Turn off domain reload and Unity enters Play Mode in well under a second instead of several. In Unity 6.6 and newer this is how new projects start out. The price is that the editor no longer throws away your managed state between runs, and the symptoms arrive one at a time: a singleton that points at an object from the previous run, a button whose click handler fires twice, a score that starts where the last session ended, a scene that behaves differently on the second Play than on the first.

This article explains exactly what Unity stops resetting, how to find every static in your project, and how to reset them so the fast Play Mode is safe to leave on.

What domain reload does, and what you lose without it

Unity runs your scripts in a managed scripting domain. By default it tears that domain down and builds it again on every Play, which is why entering Play Mode takes seconds in a large project, and also why every static field starts from its initializer each time. Unity's manual states the consequences of turning the reload off plainly:

That is the whole mechanism. Nothing is "leaking"; the objects simply still exist because the domain they live in was never destroyed. Two things are still reset: scene objects, because Unity reloads the scene (unless you turn that off too), and anything that is reinitialized by code at the start of a run.

Note that Unity still performs a domain reload when it recompiles scripts. So the problem only shows between two Play sessions with no code change in between, which is exactly the loop you are in while tuning gameplay.

The four kinds of static, and which ones matter

Not every static is a problem. Sort them by what can change after the type is initialized:

The rule of thumb: anything that is assigned, incremented, subscribed to or added to during play needs a reset.

Resetting: the attribute Unity recommends

Unity's answer is a static method that runs at the start of every Play session, with or without domain reload, before the first scene loads:

using UnityEngine;

public class Spawner : MonoBehaviour
{
    public static Spawner Instance { get; private set; }
    public static int SpawnCount;
    public static event System.Action<Spawner> Spawned;

    [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
    private static void ResetStatics()
    {
        Instance = null;
        SpawnCount = 0;
        Spawned = null;
    }
}

SubsystemRegistration is the earliest load type, which matters: a reset that runs at BeforeSceneLoad or later is too late for code that touches the static during scene loading. Unity's manual also shows resetting on exit through EditorApplication.playModeStateChanged, and recommends unregistering static event handlers on exiting Play Mode, but it adds a caveat worth repeating: code that also runs in Edit Mode can modify a static after your exit handler ran, so the entry reset is the one you can rely on.

Three details that come up in practice:

Unity 6.6: letting a generator write the reset

From Unity 6.6 there is a second route. Mark a static member with [AutoStaticsCleanup] and a source generator resets it on entering Play Mode: for a non-readonly field it captures the initializer expression and re-evaluates it on every transition, and for a readonly collection it keeps the instance and calls Clear(). Members that genuinely should persist are marked [NoAutoStaticsCleanup]. The matching analyzer (rules UAL0010 to UAL0014) reports statics that carry neither attribute.

Read the constraints before adopting it project-wide, because they are the reason the manual route still exists:

Both routes work on 6.6. On 6.3 LTS the attribute route is the only one.

Finding them all

The hard part is not the reset, it is the inventory. A project of moderate size has hundreds of statics spread over your own code, third-party assets and packages, and the editor has no window that lists them. Three ways to build the list:

Whatever you use, check the result once with domain reload off: enter Play Mode twice without recompiling, and anything that differs between the two runs is a static you missed.

Why this now matters beyond the editor

Two external reasons to do this work this year rather than later. Unity 6.6 made the fast Play Mode the default for new projects, so anyone who opens your package in a fresh project gets the stale-statics behavior out of the box. And the Asset Store's submission guidelines, updated in October 2026, require packages submitted from Unity 6.6 to support Play Mode without domain reload; a package whose statics survive between runs is now a review failure, not a quirk.

Where Static State Auditor fits

Static State Auditor is the reflection approach from the list above, packaged as a free editor window. Press Scan and every static field, auto-property and event in your assemblies is listed with its classification (mutable, event, reference, constant), whether its class already has a SubsystemRegistration reset, and a double-click that opens the declaration. The status line reads your Enter Play Mode settings and says what they mean for the list, and the view exports to CSV with the project, Unity version and settings in the header. Editor-only, no runtime code, no dependencies, Unity 6.3 LTS and newer.

Static State Auditor Pro (14.99 USD) writes the reset method, either into a generated file with one SubsystemRegistration method per class or straight into your class, and takes a snapshot of every static when Play starts and stops so it can show which ones actually changed and which survived the run. That turns the list into evidence.

Both are submitted to the Asset Store and in review as of this writing. What neither does: they do not change your code without a click, and they do not scan packages by default (a toggle includes them).

Sources

More guides

All guides · Atom feed