Simulate multiple Rooms at the same time, within one Unity instance
Multi-Room Simulators are Room Simulators which are able to simulate multiple game rooms at the same time - one sim to rule them all!
In order to achieve this, the game code should be defensive on which room it is affecting. Game state should be kept per Room, meaning game managers, singletons (static data), etc. need to account for this.
Each Room is held in a different scene. So for every Room created, the Multi-Room Simulator should open a connection to it, hence loading additively a scene and stablishing a Simulator connection (via MonoBridge).
By using Multi-Room Simulators, the coherence Developer Portal is able to instruct your Simulator which room to join and start simulating.
This communication happens via HTTP. An HTTP server is started by your game build when the
MultiRoomSimulatorcomponent is active. This component listens to HTTP requests made by the coherence Developer Portal.
For offline local development, you can use a
MultiRoomSimulatorLocalForwardercomponent on your clients, which will create HTTP requests against your local simulator upon client connection, like joining a room.
MultiRoomSimulatorreceives a request to join a room, it spawns a
CoherenceSceneLoaderthat will be in charge of loading additively the scene specified.
The quickest way to get Multi-Room Simulators set up is by using the provided wizard.
Wizard at coherence > Simulator > Multi-Room Simulator Wizard
It will take you through the GameObjects and Components needed to make it happen.
Here's a quick overview video of the setup:
These are the pieces needed for Multi-Room Simulators to work:
- In the initialization scene (splash, init, menu, ...)
- MultiRoomSimulator — listens to join room requests and delegates scene loading (by instantiating CoherenceSceneLoaders)
- (Only for local development) In the scene where you connect to a Room (where you have the Sample UI or your custom connection logic)
- MultiRoomSimulatorLocalForwarder — requests the local MultiRoomSimulator to join rooms when the Client connects.
- In the scene where the networked game logic is (game, Room, main, ...)
- MonoBridge — handles the connection
- LiveQuery — filters Entities by distance
- CoherenceScene — when the scene is loaded via CoherenceSceneLoader, it will try to connect using the data given by it. It attaches to the MonoBridge, creates a connection, and handles auto reconnection. If a scene loaded through CoherenceSceneLoader doesn't have a CoherenceScene on it, one will be created on the fly.
There are two components that can help you fork Client and Simulator logic, for example, by enabling or disabling the MultiRoomSimulator component depending on whether it's a Simulator or a Client build. These are optional but can come in handy.
- SimulatorEventHandler — events on the build type (Client/Simulator).
- ConnectionEventHandler — events on the connection stablished by the MonoBridge associated with that Scene.
Hierarchy view with additional coherence controls
It is possible to visualize each individual Room the Multi-Room Simulator is working on. By default, Simulator connections to Rooms are hidden, as shown in the image above. You can toggle the visibility per scene by clicking the Eye icon. You can also change the default visibility of the loaded scene (defaults to hidden) on the CoherenceScene component:
Scene visibility options, when this scene is loaded through CoherenceSceneLoader (hence via MultiRoomSimulator)
Working with Multi-Room Simulators needs your logic to be constrained to the scene. Methods like FindObjectsOfType will return objects in all scenes — you could affect other game sessions!
This is also true for static members, e.g. singletons. When using Multi-Room Simulators, there need to be as many isolated instances of your managers as there are open simulated rooms.
For example, if you were to access your Game Manager through
GameManager.instance, now you'll need a per-scene API like
There may be third-party or Unity-provided features that can't be accessed per scene, and that affect the whole game.
Loading operations, garbage collections, frame-rate spikes... all these will affect performance on other sessions, since everything is running within the same game instance.