Offline gameplay

How coherence behaves when a Client is not connected

Even though coherence is a networking solution, there might be instances when a Scene configured for online play is used offline, without connecting to a Replication Server. This can be useful for creating gameplay that works in an offline game mode (like a tutorial), or simply a game that can connect and disconnect seamlessly during uninterrupted gameplay.

The ability to create Prefabs and code that can be used both online and offline is an great tool that in the long term can streamline the development process, avoid duplicated code, ultimately creating less bugs.

Dos and Don'ts

To ensure that the code you write doesn't break when offline, follow these recommendations:

  • Check if a CoherenceBridge is connected using CoherenceBridge.isConnected.

  • CoherenceSync components also have a reference to the associated bridge, so if one is present in the Scene you can use sync.CoherenceBridge.isConnected for convenience.

  • When offline, CoherenceSync.EntityState is null. Use this to your advantage to identify the state of the connection.

  • Authority is assumed on offline entities (CoherenceSync.HasStateAuthority always returns true).

  • You can use commands. They will be routed to local method calls.

  • When offline, some events on coherence components (e.g., CoherenceBridge.OnLiveQuerySynced) won't be fired, so review any game logic that depends on them.

  • Persistence and uniqueness are not resolved when offline, so don't make assumptions about their network state.

  • When offline, if you have a Prefab in the Scene that is set to Simulate In Server Side, it won't be automatically removed (since there's no connection, hence coherence can't infer if it's a Simulator or a Client connection). You can use SimulatorUtility.IsSimulator in an OnEnable() and deactivate it.

  • In case of a server-authoritative scenario using CoherenceInput, you might want to isolate state-changing code that would run in the Simulator into its own script. This way, it can be reused to directly affect the state of the entity when the game is offline.

See below for a more in-depth description of how the different components behave.

Components behavior when offline

This section describes how the different components offered by coherence behave when the game is offline.

CoherenceBridge

Because the CoherenceBridge never tries to connect, it won't fire any connection-related events.

You won't be able to query the list of ClientConnections, and all Room or World related data or Services data won't be there.

However, you will be able to access through the CoherenceBridge what is part of the setup at edit time. For instance, you will be able to inspect the list of CoherenceSyncConfig objects in order to instantiate connected Prefabs.

CoherenceSync

Connected Prefabs that feature a CoherenceSync can be instantiate and destroyed like usual while offline.

Authority

Because it's always the local Client that creates instances of connected Prefabs, it will automatically receive full authority on all of them. Consequently, the OnStateAuthority callback will be invoked when the object is instantiated, in OnEnable(). Check on sync.HasStateAuthority will return true, as early as Awake().

The Client has authority to manipulate its state, and can destroy the Prefab instance at will.

If a Component has been configured to be enabled/disabled as a result of authority changes (that is, using Component Actions), it will be enabled.

Network Commands

No change in behavior. Network Commands will invoke the corresponding method with a direct invocation, with no network delay incurred.

Persistent entities

Prefabs marked as Persistent will not persist after an offline game session. They will be destroyed when the Scene they belong to is unloaded, and will not be automatically recreated if the Scene is re-loaded.

Persistence is tied to the World or Room the Client is connected to. If you need objects to persist between different offline sessions, you need to store their state some other way.

Unique entities

Like persistence, uniqueness is also verified within the context of the Room or World the Client is connected to, and is generally used for ensuring that a different Client can't bring an already existing entity to the simulation.

When offline, no check happens for uniqueness, meaning that unique entities can be instantiated multiple times. It is therefore up to the local gameplay code to make sure this doesn't happen in the first place.

Simulate in Server-side

Any Prefab for which the property Simulate In has been set to Server-Side will not be automatically deactivated on instantiation.

To ensure such a Prefab doesn't appear in an offline session, make sure to deactivate it in its code by using:

if (!SimulatorUtility.IsSimulator)
{
    gameObject.SetActive(false);
}

LiveQuery

LiveQuery components will not have any effect offline. However, keep in mind that they will try to find the CoherenceBridge, so if none is present they will throw an error. For this reason it's a good idea to keep them together, and only have a LiveQuery in the scene if a CoherenceBridge is present.

CoherenceNode

Any CoherenceNode component will have no effect. There are no drawbacks for leaving it inside the Prefabs.

CoherenceInput

Given that it's inherently meant to be used in a Client-Server scenario, CoherenceInput has no meaning offline.

However, you can safely leave the component on your Prefabs, and architect your scripts so that rather than sending inputs to CoherenceInput regardless, they first check if the Client is connected and, in case of a negative answer, manipulate the entity's state instead.

It can be a good idea to isolate the code used to manipulate the entity's state during prediction, and reuse it for offline behavior.

  • If the game is online, input is sent to the Simulator via CoherenceInput, while at the same time prediction is done locally and applied. On the Simulator, the same code used from the Client to do prediction is used to compute the final state. Once an update is received, reconciliation code kicks in and corrects any mismatches.

  • In offline mode, the same code used for the prediction is used for driving the entity's state instead, and no input is forwarded to CoherenceInput.