Skip to content

Bootstrap Flow

Mika Notarnicola edited this page Jul 18, 2026 · 8 revisions

The Play Mode Bootstrap Flow

This page traces exactly what happens from the moment you press Play in the editor through to a fully initialized game, and back again when you stop. It's the mechanism behind the second goal described on the Home page: hitting Play always runs the same flow and returns you to the scenes you were editing.

1. Exiting Edit Mode

When you hit the Play button, the Unity editor begins the process of exiting edit mode. This is where the Bootstrap flow begins.

If the Editor Flow Enabled project setting is off, none of the following happens and Play mode just starts on whatever scenes are loaded, with no bootstrap redirect at all.

Assuming it's on:

  1. Any unsaved untitled scene forces a save prompt. If you decline, Play mode is cancelled outright.
  2. Bootstrap resolves which environment to boot: it checks whether the active scene has a specific environment mapped to it, and falls back to the project's Default Play Mode Environment if not. If neither resolves to anything, setup stops here and Play mode starts on the active scene unchanged.
  3. EditorSceneManager.playModeStartScene is set to the bootstrap scene (the first valid entry in the project's Scenes in Build list). Unity will load this scene when entering play mode, regardless of the scenes you had open in edit mode.
  4. Every other currently open scene, along with your current object selection, is recorded and saved to SessionState alongside the resolved environment. SessionState survives the transition into Play mode, which is how the flow finds its way back to your original scenes later.

2. Entering Play Mode

The play mode bootstrap sequence starts from a RuntimeInitializeOnLoadMethod callback, the earliest point Unity offers to run code once a scene starts loading. This callback is what runs in a build too, just with a build-specific AppInstance in place of the editor's.

From there, an AppInstance is created and stepped through a fixed sequence of states:

State What happens
BootstrapHandlerDiscovery Determines which pre/post bootstrap handlers will run this session (the environment can supply its own; otherwise Bootstrap's defaults are used).
PreBootstrap Runs the pre-bootstrap handler, before any service exists.
ServiceDiscovery Clones the environment's Service List asset and reads the it's entries, sorting them by init priority.
ServiceBinding Registers each service under its type (and any additional types it declares) so it can be located later.
ServiceInit Calls InitService on every service, in priority order.
AsyncTaskFlush Waits for any work services scheduled during init to finish.
PostBootstrap Runs the post-bootstrap handler, now that every service is live.
Ready Bootstrap is complete.

See Services for what happens during service discovery, binding, and init in more detail.

3. Getting Back to Your Scenes

Restoring your original scenes and selection happens as part of the default post-bootstrap handler, which runs after every service has finished initializing.

  • If you had other scenes open (recorded in step 1), they're loaded back now: the first one (the "active scene" from edit mode) replaces the bootstrap scene, and the rest are loaded additively alongside it. If you didn't have any other scenes open, the scene at index 1 is loaded instead.
  • Your original object selection from edit mode is restored a couple of frames later, once the reloaded scenes have had a chance to run their own Awake calls. Due to editor limitations any scene foldouts will remain collapsed, but the inspector should still reflect your restored selection.

This step is skipped entirely during Play mode test runs, so tests aren't disturbed by scene reloads.

If an environment supplies its own custom post-bootstrap handler, this restoration step doesn't happen automatically. A custom handler that wants scene/selection restoration needs to invoke it itself.

4. Stopping Play Mode

Stopping Play mode happens in two steps:

  1. On ExitingPlayMode, the running AppInstance is told to quit. Every service that implements IDisposable is disposed, and the cloned service list used for this session is discarded.
  2. On EnteredEditMode, the play-mode AppInstance reference is finally dropped, playModeStartScene is reset back to null, and a fresh edit-mode AppInstance is initialized from the project's Edit Mode Services list. This runs its own, much shorter bootstrap: discovery, binding, and init only, with no pre/post-bootstrap handlers involved.

Unity itself is responsible for restoring your original scene setup when Play mode ends. That part isn't something Bootstrap needs to manage; it's native editor behavior independent of playModeStartScene, which only affects what loads when entering Play mode.

Notable Edge Cases

  • Editor Flow disabled, or no environment resolves for the active scene: Play mode starts on the active scene directly, with no redirect and no service bootstrap.
  • No valid scene at the top of the Scenes in Build list: same fallback as above; a warning is logged.
  • Recompiling scripts while an AppInstance is running forces Play mode to stop and tears down whatever instance was live, since the domain reload would otherwise leave it in an invalid state.
  • Bootstrap also exposes a manual reset (App.Reset()) that tears down and re-runs the same sequence on demand, without an actual Play mode transition.

Bootstrap flow in builds

Everything above is editor-only up through step 1. In a standalone build there's no editor and no "exiting edit mode" step: the build's first scene already is the bootstrap scene, so there's nothing to redirect, and the environment used is the project's Default Build Environment instead of the Default Play Mode Environment. A build effectively starts at step 2.

There's also no edit-mode scene state to return to in a build, so step 3 doesn't apply either. A build's post-bootstrap handler just loads the next scene after the bootstrap scene, instead of restoring anything.

Clone this wiki locally