#Big Scene, clients wait double long on SceneManager.LoadGlobalScenes(...)

48 messages · Page 1 of 1 (latest)

fickle valley
#

I have run across an interesting "non-problem" that I'm not sure exactly how to work around. I am working on a game that a server listens for clients to connect, and once clients are ready, the server runs

SceneManager.LoadGlobalScenes(new SceneLoadData("MainGameplay"))

This works! But the scene is rather large and takes 30ses-1min to load. However, the clients don't start loading the scene until after the server loads. So this can take the clients 1min-2min to load.

Thanks for the read! Are there any suggested ways to work around the clients waiting for server to load before they start loading?

young bridge
#

but if you want the simplest solution

#

I suggest simply adding a loading screen to clients while the server & the client load the scene

fickle valley
#

Thanks @young bridge ... loading screen is def. a good idea... I am going to keep looking for some solutions. It seems like the deadtime the client is waiting could be circumvented... The multiple scene idea can possibly work for me too. I can possibly separate the static (really heavy) objects and have that loaded as a non-networked scene [loaded immediately on GO!] and dynamic stuff loaded as a network scene... an interesting thought...

abstract cloudBOT
#

Gave +1 Rep to @young bridge

arctic orchid
#

Something I've never tried but worth giving a shot...

#

After server starts load the scene with normal scene manager, not FN.

#

Then when client connects load as global

#

Should keep network stuff inactive until load global is called

fickle valley
#

now that's the witchcraftery i'm looking for! thanks @arctic orchid 😛

abstract cloudBOT
#

Gave +1 Rep to @arctic orchid

arctic orchid
#

let me know if it works 😄

fickle valley
#

Messing with this now... OK... When GO is pressed:

Attempt 1
• Server and Clients immediately load scene locally
• When Server is loaded locally SceneManager.LoadGlobalScene() is called.

Results 1
• Works fine if all clients are already loaded.
• Breaks if server loads before client. Error
• Unity tries to set active scene while client is still loading [exception error]
• Even if I add code to __LoadScenes() [phew that was a big function] add alreadyLoaded scenes into loadedScenes [and it actually wait for scene to load...] I get another exception error
• Cannot add scene to broadcastLookupDatas, collection is full.
• Probably due to the backed up packets being sent from server player.

... so onto Attempt 2.

#

Attempt 2
• Server and Clients immediately load scene locally
• When scene is loaded, call SceneManager.LoadConnectionScenes( currentConnection, ...)

** Results 2**
• Err, ok, failed quick... LoadConnectionScenes() is a server only command 😛

fickle valley
#

Attempt 3
• Server and Clients immediately load scene locally.
• Server call SceneManager.LoadConnectionScene(...) on local load finish
• Client broadcast <OnLocalSceneChange> to Server
• Server calls SceneManager.LoadConnectionScene(client,...)

** Result 3**
• Coming soon...
• Cancelled!

arctic orchid
#

@fickle valley you're possibly doing it wrong

#

Load locally on server using unity scene manager.

#

When a client connects load globally

#

that will automatically tell the client to load it

#

and if you want to disable things when the client drops out just despawn all nobs

fickle valley
#

Load locally on server using unity scene manager.
When a client connects load globally

In my case, everyone is already connected in a lobby and about to load a big scene. My attempt is when the GO button is pressed, server loads first, then the clients... I want everyone to start loading immediately, and then after loaded, start hashing things out... at least that's the plan. Trying to make that nice UX.

arctic orchid
#

but you want server having it loaded first to save time right

#

thats what im recommending

fickle valley
#

not sure I understand? Maybe tell me again? I don't want to wait for the server to load first, because it is a big scene.

arctic orchid
#

right okay

#

something like this...

#
ServerManager.OnServerConnectionState
    if (args.State == Connected...)
      UnityEngine.SceneManager.LoadScene(theBigOne);//I know this api call is wrong.```
#
void AllClientsHitOK()
{
    InstanceFinder.SceneManager.LoadGlobal....(theBigOne);//obv build SLD
}```
#

the loadglobal will activate the scene and tell clients to load it

fickle valley
#

ooooo, really? wait.... let me review attempt 1 more time

#

oooo

#

man

#

yeah

#

should

#

work!

#

Attempt 4
• Only Server immediately load scene locally.
• Server then calls SceneManager.LoadGlobalScene() while loading to trigger the clients to start loading

Results 4
• Exception Error from Attempt 1 (can't set ActiveScene while scene is loading)... I could put the fix I had for attempt 1... but that will simply wait for Server to load before broadcasting the scene load to clients causing the original issue.

#

I'm going to resume attempt 3, but need a bit of a break... thank you @arctic orchid for the help! I know I'm close!

abstract cloudBOT
#

Gave +1 Rep to @arctic orchid

arctic orchid
#

what happened to attempt 4 lol

fickle valley
#

exception error ... i "editted" the post with the result

arctic orchid
#

is that error on clients or server

#

I'll see what I can find because I kind of expect #4 to work

fickle valley
#

I'm on a version back 2.5.4 Pro

SceneManager.__LoadScenes():1075
SceneManager.SetActiveScene():1925

is where the exception lies

arctic orchid
#

okay ty

fickle valley
#

Attempt 3 Revisited
• Server and Clients immediately load scene locally.
• When Server load finish, call SceneManager.LoadConnectionScene(...) [And SceneManager.LoadConnectionScene(ClientHost,...) if applicable]
• When Client load finish, client broadcast <OnLocalSceneChange> to Server
• On Server Receive Broadcast, Server calls SceneManager.LoadConnectionScene(client,...)

** Result 3**
• If all clients are loaded before server, this works great!
• If server loads before client, clients loaded before server are not visible (visible on server, invisible on client, no gameobject at all)

Probably more the look at, but yeah... can't find my happy place tonight! Tomorrow is another day! Night! 🙂 🌛

fickle valley
#

Added a patch which will be good enough for now... so to recap.

When Host "GO"

ClientLocalSceneChangeBroadcastListener.Listen();
await UnityEngine.SceneManagement.SceneManager.LoadSceneAsync("MainGameplay");
sceneManager.LoadConnectionScenes(new SceneLoadData("MainGameplay"));
sceneManager.LoadConnectionScenes(clientManager.Connection, new SceneLoadData("MainGameplay"));```

When Clients "GO"
```csharp
await UnityEngine.SceneManagement.SceneManager.LoadSceneAsync("MainGameplay");
InstanceFinder.ClientManager.Broadcast(new ClientLocalSceneChangeBroadcast{ sceneLoadData = new SceneLoadData("MainGameplay") });```

On Server Receive Broadcast
```csharp
private static void OnClientLocalSceneChangeBroadcast(NetworkConnection conn, ClientLocalSceneChangeBroadcast data)
{
    InstanceFinder.SceneManager.LoadConnectionScenes(conn, data.sceneLoadData);
}```

The Patch (wait for host and all clients to be in scene before spawning) [this might just be something wrong on my side?]
```csharp
private void OnClientPresenceChangeStart(ClientPresenceChangeEventArgs clientPresence)
{
    // Some pre-checks
    // Check if all clients are in scene
    foreach(var (id, client) in _networkManager.ServerManager.Clients)
            if (!client.Scenes.Contains(gameObject.scene)) return;
    // Spawn Players
}```
#

And @arctic orchid ... after re-reading your post, I finally understand what you were trying to get through my thick skull... server should start loading the level as soon as server is started [before clients are connected]... a very interesting thought indeed.... it was not in my design, but it may soon change... as mentioned above, i have the work around... butttt, dang, yeah. that really makes alot of sense! 😛