Skip to content

GameInstance, Travel, and Bootstrap

Bootstrap starts RedEngine. GameInstance owns one runner and the application-level services around it. Travel destroys the old runner/world pair and creates a new pair for the requested scene. In the Editor, Multi-Peer creates several game instances inside one Unity process.

Execution model

  • Authority — the server controls synchronized network scene changes and world gameplay state.
  • Prediction — travel and additive scene loading are not Input-Authority prediction.
  • Replicated — Fusion scene information and the network actors created in the destination world.
  • Local only — loading screen, progress, fades, selected Multi-Peer view, camera, and audio transition.

Bootstrap pipeline

After Unity loads the initial scene, RedEngine.Runtime.Bootstrap performs this sequence:

  1. load the single EngineSettings asset from Resources;
  2. initialize ContentManager with ContentInitializationOptions;
  3. read startup arguments and the Editor peer count;
  4. create and await a server GameInstance when server mode is enabled;
  5. create one or more clients in parallel after the server session is available;
  6. select the first client as the input-producing instance;
  7. use one explicit Fusion session name for the server and all local clients.

On application shutdown or when leaving Play Mode, bootstrap waits for content initialization, shuts down every game instance, then shuts down ContentManager.

EngineSettings controls startup

Keep one asset at Assets/Resources/EngineSettings.asset. It supplies:

  • the concrete GameInstance type;
  • the NetworkRunner prefab;
  • default client and server maps;
  • default server port;
  • content initialization options.

The concrete base GameInstance is valid. Create a subclass only when the project needs additional application-level behavior or subsystems.

TravelURL forms

TravelURL represents both local and network travel, plus case-insensitive query options:

text
/Arena
/Arena?Difficulty=Hard
127.0.0.1:27015/Arena
127.0.0.1:27015/Arena?listen
127.0.0.1:27015/Arena?session=Development
127.0.0.1:27015/Arena?Spectator
  • a URL without a host starts Fusion in Single mode;
  • a URL with a host starts a client;
  • the listen option starts a server;
  • the session option selects the Fusion session shared by server and clients;
  • MapName removes directories and the scene extension;
  • url["Option"], Contains, and GetValue<T> read options.

Use TryParse when the URL comes from a player or command line. The implicit string conversion is convenient for trusted literals.

Start travel and observe it

csharp
GameInstance instance = GameInstance.PrimaryGameInstance!;

instance.OnBeginLoadWorld += url => loadingOverlay.Show(url.MapName);
instance.OnWorldLoadComplete += world => loadingOverlay.Hide();
instance.OnTravelFailure += (url, reason) => ShowTravelError(url, reason);

await instance.BrowseAsync(
    "127.0.0.1:27015/Arena?Team=Blue");

Browse(scene, options) builds a local URL. Browse(url) starts travel without awaiting it. BrowseAsync(url) returns the travel task. Observe OnWorldLoadComplete and OnTravelFailure when the caller needs the outcome and structured TravelFailureReason.

What happens inside BrowseAsync

  1. resolve the scene through ContentManager;
  2. shut down and destroy the current runner;
  3. instantiate the runner prefab from EngineSettings;
  4. create a new World and connect it to FusionSceneManager;
  5. call NetworkRunner.StartGame with single, client, or server mode;
  6. wait for Fusion's simulation scene, with a 30-second timeout;
  7. initialize the world and its subsystems;
  8. wait for the local PlayerController and, when the GameMode has a default character prefab, its spawned character pawn;
  9. publish OnWorldLoadComplete.

Failures are reported as TravelFailureReason values for map resolution, connection, scene timeout, world initialization, local-player spawn timeout, or an unknown startup problem. WidgetSubsystem listens to the travel events to show and hide the configured loading screen automatically. A loading screen's registered hideAnimation completes before the widget is destroyed, so it can cover the full technical spawn and then leave with a short transition.

Only one travel runs at a time. Additional Browse requests are queued and processed in order after the current request. Completed work does not prevent later travel; startup failures are reported through OnTravelFailure before the incomplete world is shut down.

Load additional levels inside the current World

Browse replaces the current runner and world. For streaming a dungeon, combat arena, or another additive part of the same match, use the current World instead:

csharp
using UnityEngine.SceneManagement;

World world = gameInstance.CurrentWorld;

await world.LoadSceneAsync(
    "Arena_UpperFloor",
    LoadSceneMode.Additive);

// The match continues in the same World and on the same NetworkRunner.

await world.UnloadSceneAsync("Arena_UpperFloor");

Both methods delegate to Fusion's NetworkRunner, so scene operations are synchronized through the active network session. Call them from state authority, use the same scene name on every peer, and make the scene available to Fusion and the active Build Profile. Actors found in a loaded scene are prepared for the existing World; this is level streaming, not a second world or a nested game mode.

Use the two scene paths for different jobs:

GoalAPI
Replace the current match, server, or mapGameInstance.BrowseAsync(...)
Add another level to the current matchWorld.LoadSceneAsync(name, LoadSceneMode.Additive)
Remove an additive levelWorld.UnloadSceneAsync(name)

Multi-Peer and the primary instance

GameInstance.Instances contains every live peer in the process. Only the instance whose ProvideInput is true is considered PrimaryGameInstance; changing it also updates Fusion input, runner visibility, camera, rendering, audio, and UI output.

Use GameInstance.SetActiveGameInstance(instance) in editor tooling. Gameplay code should usually find its owning world or call TryGetGameInstance(runner) rather than assuming the first instance. Dedicated server instances cannot become primary and are omitted from the Editor peer selector.

Next: GameMode pipeline.

Updated:

RedEngine Framework documentation