Unity 6.5 Enter Play Mode Freezes on Domain Reload Off - Static State and Initialization Order Fix

Problem: Unity 6.5 freezes when you press Play after turning Domain Reload Off in Enter Play Mode Options.

This usually happens because your project is relying on a clean script-domain reset that no longer happens between play sessions. With domain reload disabled, static fields, singleton state, event subscriptions, and cached service references stay alive. If startup code assumes those values begin empty every time, the editor can hang during bootstrap, scene load, or first-frame initialization.


Quick fix checklist

  1. Reproduce the freeze with Domain Reload Off and confirm it disappears when Reload Domain is re-enabled.
  2. Reset static state explicitly at startup using RuntimeInitializeOnLoadMethod.
  3. Audit singletons, service locators, and cached scene references for stale state between play sessions.
  4. Reorder initialization so no system reads another service before it is rebuilt.
  5. Remove duplicate event subscriptions caused by play sessions reusing the same static delegates.
  6. Validate Play Mode entry twice in a row after each change.

Root cause summary

When Reload Domain is enabled, Unity rebuilds the managed scripting world before Play Mode.
When Reload Domain is disabled, Unity skips that reset for faster iteration.

That means the following can survive from the previous session:

  • static fields
  • singleton instances
  • event listeners on static events
  • cached ScriptableObject or service references
  • flags that say a system is already initialized

The freeze usually comes from one of these patterns:

  • A bootstrapper exits early because isInitialized == true, leaving dependent systems waiting forever.
  • A singleton points to a destroyed MonoBehaviour or scene object from the previous session.
  • Two systems subscribe repeatedly to the same event and trigger recursive initialization.
  • Script execution order changed, so one service now reads another before reset code runs.

Step-by-step fix

Step 1 - Confirm Domain Reload Off is the trigger

Open Edit -> Project Settings -> Editor -> Enter Play Mode Options.

Test these two states:

  1. Reload Domain On
  2. Reload Domain Off

If the freeze only appears when Reload Domain is disabled, you are not dealing with a general engine crash. You are dealing with state persistence between play sessions.

Verification: Unity enters Play Mode normally with reload on, but freezes or stalls with reload off.


Step 2 - Reset static state manually on startup

Any system that previously relied on domain reload should now be reset deliberately.

Good candidates:

  • singleton instance pointers
  • bool initialized
  • cached service registries
  • static queues, dictionaries, or ID counters

Example:

using UnityEngine;

public static class GameBootstrapState
{
    public static bool IsInitialized;
    public static int SessionCounter;
    public static PlayerRuntime CurrentPlayer;

    [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
    private static void ResetStatics()
    {
        IsInitialized = false;
        SessionCounter = 0;
        CurrentPlayer = null;
    }
}

SubsystemRegistration is a strong first place to reset statics for Enter Play Mode workflows because it runs before scene objects begin normal startup.

Common mistake: Resetting only the "main" singleton while forgetting helper caches, static events, or factory registries that still carry stale state.


Profiler, Package Manager, or domain reload timing stalls

Sometimes the editor looks frozen during Play entry even though your gameplay scripts are fine.

Checklist:

  1. Close Profiler deep profiling if it is attached while you reproduce the stall. Deep profile can block the main thread during the first frames after Play starts.
  2. Pause Package Manager resolve windows and large asset store downloads during repro. They can contend with script compilation and scene load on the same thread.
  3. If you reset statics in RuntimeInitializeOnLoadMethod, confirm you are not doing heavy synchronous work there (disk IO, large JSON parse, full catalog rebuild). Move that work behind a deferred frame or an explicit loading screen.

Pro tip: If the freeze correlates with the first Addressables catalog load, run the preflight discipline in Addressables Profile Variable Preflight Checklist so remote init does not fight Domain Reload Off assumptions.


Step 3 - Audit initialization order, not just data reset

After you clear statics, check the order your systems start:

  1. config and bootstrap data
  2. core services
  3. save/profile state
  4. gameplay scene systems
  5. UI listeners and late subscribers

If a service checks another system before that system has rebuilt cleanly, you can get a hidden stall or loop.

Look especially for:

  • Awake() reading global services too early
  • OnEnable() subscribing before bootstrap finishes
  • async startup tasks waiting on state that was never reset

Verification: Add temporary logs around startup order and confirm the freeze stops at a specific system if it still hangs.


Step 4 - Remove stale event subscriptions

With domain reload off, static delegates and long-lived event buses can keep old listeners.

Check for:

  • static Action or event fields
  • editor-only event hooks
  • service bus subscriptions in OnEnable() with no matching unsubscribe

Use the usual pairings consistently:

  • subscribe in OnEnable()
  • unsubscribe in OnDisable()

or

  • register in bootstrap
  • unregister in teardown

Alternative fix: If your architecture uses a global event bus, add an explicit ClearAllListenersForPlayMode() route in your startup reset path for editor-only safety.


Step 5 - Rebuild singletons safely

Singletons are one of the biggest sources of Domain Reload Off freezes.

Bad pattern:

  • static instance survives
  • referenced GameObject was destroyed
  • new scene starts
  • code sees non-null instance and skips init

Safer pattern:

  • validate the instance is still alive
  • recreate if the target object was destroyed
  • reset editor-only persistent state on Play Mode entry

Check:

  • DontDestroyOnLoad managers
  • service locator registries
  • audio/input/network bootstrap objects

Verification: After exiting Play Mode, enter again twice and confirm only one instance exists for each core manager.


Step 6 - Add one editor diagnostic guard

During troubleshooting, add a minimal guard so broken startup state is obvious instead of silently freezing:

using UnityEngine;

public class StartupWatchdog : MonoBehaviour
{
    private float _startTime;

    private void Awake()
    {
        _startTime = Time.realtimeSinceStartup;
    }

    private void Update()
    {
        if (Time.realtimeSinceStartup - _startTime > 5f)
        {
            Debug.Log("Startup watchdog still active - verify bootstrap completion order.");
            enabled = false;
        }
    }
}

This is not the permanent fix. It simply helps you narrow down whether the freeze is really "hard" or whether the project is stuck in a broken initialization path.


How to verify the fix worked

Run this exact loop:

  1. Enter Play Mode
  2. Exit Play Mode
  3. Enter Play Mode again
  4. Change scene or trigger your normal bootstrap path
  5. Exit and repeat one more time

Then confirm:

  • no freeze on Play Mode entry
  • no duplicate managers
  • no stale UI or input state from prior session
  • no console spam suggesting repeated subscriptions or already-initialized services

If all checks in the loop above pass, your Domain Reload Off workflow is stable enough for daily iteration.


Alternative fixes

  • Re-enable Reload Domain temporarily for the current milestone if your architecture is not ready for persistent editor state.
  • Leave Reload Domain Off but keep Reload Scene On while you isolate the problem.
  • Move risky bootstrap logic out of static constructors and into an explicit runtime initialization path.
  • Add a dedicated editor-only reset utility for debug systems, test harnesses, and tooling singletons.

Prevention tips

  • Treat Domain Reload Off as an architectural mode, not just a performance toggle.
  • Keep one checklist for every new singleton: creation path, teardown path, stale-instance check, event unsubscribe path.
  • Avoid using static references to scene objects unless you also own their reset behavior.
  • Test Play Mode entry at least twice whenever you touch bootstrap, save systems, networking, or input initialization.
  • Add a small smoke-test scene specifically for startup validation.

FAQ

Why does Unity freeze only when Reload Domain is off?
Because your code is keeping old managed state alive between sessions, and some startup path assumes that state begins empty.

Should I stop using Domain Reload Off entirely?
Not necessarily. It can be a great iteration-speed tool, but only once your bootstrap code explicitly resets the state that used to be cleared automatically.

Are static constructors the problem?
Sometimes. The bigger issue is usually hidden state persistence, not the constructor alone. Static constructors become risky when they trigger work that expects a fresh play session every time.

Should I reset state on EditorApplication.playModeStateChanged instead of SubsystemRegistration?
Either can work, but SubsystemRegistration is usually the safer default because it runs early and predictably for Enter Play Mode workflows. If you must use playModeStateChanged, reset only on ExitingEditMode and keep the handler tiny so you do not create new ordering hazards.


Related links

Bookmark this fix for quick reference the next time your project starts "randomly" hanging on Play. If it helped, share it with another Unity developer working with fast iteration settings.