"CreateLobby is async — IsActive is still false on the same frame"
▸ SYMPTOM
Two related symptoms from the same root cause:
-
Every hosted session falls through to the offline/solo path even when hosting succeeds. A "Play" button that calls
CreateLobby()then checksNetworking.IsActivealways takes thefalsebranch on the same frame, causing the game to run the solo-possess path instead of waiting for the lobby to come up. -
The "Stop Server" button appears to do nothing. The session-end path sets the mode to idle and calls
Networking.Disconnect()but never un-possesses the player — the host stays in character view with the generator UI disabled. The button fires; the state just never changes back to the pre-session view.
▸ CAUSE
Networking.CreateLobby(...) is async — Networking.IsActive is still false on the same frame you call it. Any code that branches on IsActive immediately after CreateLobby takes the wrong branch:
// BUG: IsActive is async-false on this frame
CreateLobby();
if ( Networking.IsActive )
return; // never reached
SoloPossess(); // always runs, even when hostingThe session-end side: an EndSession method that only flips a mode enum and calls Disconnect() but never un-possesses the character leaves the host stuck in the character view — the "pointer-events: none" suspicion is a red herring; the state just never returned to the authoring view.
▸ FIX
Part 1 — gate on the synchronous source of truth. Use your own mode enum (which you set on the same frame as CreateLobby) instead of Networking.IsActive:
void Play()
{
Mode = SessionMode.Hosting; // synchronous — set this frame
CreateLobby();
if ( Mode == SessionMode.Hosting )
return; // trust the async auto-possess poll to walk the host in
// Fallback: solo mode
SoloPossess();
}Add a timed watchdog (~4 seconds): if Networking.IsActive is still false at timeout, fall back to the offline solo path so the one-click action always does something even with Steam offline.
Part 2 — un-possess on session end:
void EndSession()
{
if ( InCharacterMode )
ExitCharacter(); // restore the pre-session view
Mode = SessionMode.Authoring;
Networking.Disconnect();
}▸ WHY IT WORKS
Your mode enum is a synchronous, immediate state change — it reflects the user's intent on the same frame. Networking.IsActive reflects the network system's state, which lags behind by at least one frame while the lobby is being created asynchronously. By gating on intent (mode) rather than network readiness, the control flow matches the user's action.
The un-possess step ensures the visual state (camera, UI, input routing) returns to the pre-session state, not just the logical mode. Without it, the host remains visually in-character with the session UI disabled.