The docs are saying that correctly: there is no need for the client to load the scene first. Client can load/unload any sub-scene with pre-spawend ghosts at will (and everything still works fine).
The problem comes to how the ghost prefab reference and registration works and the fact the client must load the necessary prefabs as demanded by the server.
When you add a ghost instance to a sub-scene, its prefab is stored in the scene itself (unless another sub-scene references the same prefab, in which case it may be stored in another archive, shared among scenes).
I will try to explain here how things works as simple as I can.
So, let’s start server side. Server load the scene, Sub-scene are loaded too, end they contains:
- Entity Prefab (because Netcode needs them to spawn ghost) if the scene entity archive does not have a reference to another archive that contains already the same prefab.
- The ghost instance (that reference that prefab)
Scene A
Pre-Spawned Ghost Instance -> Ghost Prefab X
Ghost Prefab X
When the first client connects and go in game (start streaming ghosts) the server sends to him the list of prefab resources that he must load (or have loaded). This is what the GhostCollectionSystem assess and throw exception if not honored by the client.
The server only stream to the client ghosts for which their associated prefabs have been loaded and processed by the client.
If the client set the connection to be in game (start receiving ghosts), and the prefabs that are needed are not loaded yet, or the resources are still loading or are going to be loaded, it is client responsibility then to inform the GhostCollectionSystem that the resources are loading and thus to wait for processing the prefab and relative hash match.
The ghost prefabs data is stored inside the GhostCollectionPrefab that contains:
- The entity associated with that prefab type
- The hash (CRC) of the prefab
- A Loading flag.
This list sent by the server to the client as part of the snapshot data, and it is the beginning of the ghost protocol exchange. This list always growth. never shrink.
The clients communicate to the server, as part of the command stream, the number prefabs (from that list, in server order) loaded so far.
When the client receives the list from the server (sent in multiple chunks), the client matches the entry in the list with any loaded prefab he has loaded and do the same process the server does to calculate a CRC (hash).
What to do if the prefab is not there yet (or we want to delay loading them later on)?
This buffer can be inspected by the client before the GhostCollectionSystem runs and set the Loading flag as LoadingActive. The flag should be set every frame until the resource is loaded (see the documentation here: Struct GhostCollectionPrefab).
How can I load/unload sub-scene with ghosts dynamically without caring about this or more in general similarly to an open-world game scenario?
A simple solution is to have a single sub-scene (or multiple, depend on how you would like to have your data organized) that contains pretty much all the ghost-prefabs. This is pre-loaded by both server and client before accepting connections and setting the connection itself as in-game.
Then you can load/unload at will any sub-scene without caring about that loading detail because you are guarateed that the necessary ghost prefabs are already loaded.