Fast Enter Play Mode and Domain Reload¶
LoL Engine is designed to be safe with Unity's Configurable Enter Play Mode when Reload Domain is disabled — the default for new projects starting in Unity 6.6. You can turn on Fast Enter Play Mode for quicker iteration and the engine still starts each Play session from a clean state. You do not need to do anything; this page explains how it works and what to follow if you add your own static state.
Why this matters¶
Entering Play mode normally rebuilds the scripting (C#) domain, which resets every static
field to its initial value and clears every static event's subscribers. Fast Enter Play
Mode skips that domain reload to enter Play faster — so without care, static state would
survive between Play sessions in the editor: a service registry still holding last
session's services, a static event still holding handlers attached to destroyed objects, a
singleton field pointing at a destroyed GameObject, an "initialized" flag stuck true.
This affects the in-editor iterate loop only. A built player always launches as a fresh process, so static state always starts clean in a build regardless of this setting.
What LoL Engine already handles (you do not need to do this)¶
Every piece of static state the engine owns is reset on each Play-enter, using the
mechanism Unity provides for exactly this purpose — a method marked
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)], which
runs at the start of every Play session whether or not the domain was reloaded. Each
system resets itself independently and idempotently (the engine's distributed-reset pattern),
covering for example:
- the logger (sinks, history, file sink, cached main-thread id);
- the
ServiceLocator(instance and registrations); - the event bus subscriber tables and the
EventRegister/EventStartListeningplumbing; - the
ModelDbcontent registry; - localization
LocStringformatters; - the
TestModegate; - the engine-initialization registry used by
ServiceAwaiter/WaitForServices; - the built-in singleton base classes (
Singleton<T>,PersistentSingleton<T>,RegulatorSingleton<T>) andImprovedGameInitializer.
So enabling Fast Enter Play Mode is safe with the engine: on the second and later Play sessions, services re-initialize, event subscriptions start empty, and singletons resolve to the live instance — exactly as they would after a full domain reload.
If you write your own static state¶
The same rule applies to your game code: any static mutable field, static event, or
custom singleton you add must reset on Play-enter, or it will hold stale values when Reload
Domain is off. Two options:
1. Reset it explicitly (non-generic types):
using UnityEngine;
public static class MyGameState
{
public static int Score;
public static event System.Action OnScoreChanged;
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
private static void ResetStatics()
{
Score = 0;
OnScoreChanged = null; // drop subscribers from the previous Play session
}
}
Note:
[RuntimeInitializeOnLoadMethod]does not fire for an open generic type (Foo<T>), because Unity has no concreteTto call it on. For a generic singleton, clear the static field from an instanceOnDestroy()instead — which is how the engine'sRegulatorSingleton<T>does it.
2. Derive from an engine singleton base class (Singleton<T>, PersistentSingleton<T>,
or RegulatorSingleton<T>) — they already null their static instance on destroy, so your
singleton is Fast-Enter-Play-Mode-safe for free.
Verifying¶
To confirm your project (engine + your code) is clean under this setting:
- Edit → Project Settings → Editor → Enter Play Mode Settings: enable Enter Play Mode Options and uncheck Reload Domain (this is the Unity 6.6 default).
- Press Play, then Stop, then Play again — at least twice.
- Confirm the second run behaves like the first: services re-initialize, no duplicated
event handlers firing on destroyed objects, no
MissingReferenceExceptionorObjectDisposedExceptionfrom leftover references, and no "already initialized" warnings.
If your own code misbehaves only on the second-plus Play, an unreset static is almost always the cause — apply one of the patterns above.
See Also¶
- Unity Manual — Configurable Enter Play Mode
- Architecture Guide — the engine's distributed static-reset design
- Service Locator, Events