Class ClientConnectionManager
Manages client connection lifecycle: connect, disconnect, reconnect with exponential backoff, and connection state tracking. Extracted from Client.cs.
public class ClientConnectionManager
- Inheritance
-
ClientConnectionManager
- Inherited Members
Constructors
ClientConnectionManager(NetworkManager)
Creates a ClientConnectionManager and subscribes to NetworkManager connection events.
public ClientConnectionManager(NetworkManager networkManager)
Parameters
networkManagerNetworkManagerThe FishNet NetworkManager to manage.
Fields
EnsureConnectionToken
Optional coroutine run immediately before every StartConnection, used to
obtain the one-time connection token the game server needs to recover this
client's real IP.
Every game server — Login, World and Scene — sits behind the same L4 UDP proxy and binds to loopback, so all of them see 127.0.0.1 as the source address and all of them reject a handshake that arrives without a token. Hooking the fetch here rather than at the individual call sites means world/scene routing and automatic reconnects get a token too, not just the login screen.
public Func<IEnumerator> EnsureConnectionToken
Field Value
Properties
CanReconnect
Returns true if the current connection type supports reconnection (World, Scene, or an in-flight world connect).
public bool CanReconnect { get; }
Property Value
Remarks
ConnectingToWorld counts. ConnectToServer(string, ushort, bool) sets it for every world connect — including the reconnects TryReconnect() issues — and FishMMO.Client.ClientConnectionManager.OnClientConnectionState(FishNet.Transporting.ClientConnectionStateArgs) clears CurrentConnectionType to None on the drop that arms the retry, so by the time an attempt fails ConnectingToWorld is the only type left describing it. Without it here, a failed reconnect read as a non-reconnectable failure: no further retry was armed, so MaxReconnectAttempts never counted past one, OnReconnectFailed (and its quit-to-login forward) never fired, and the client sat disconnected with no path forward. lastWorldAddress is assigned before StartConnection on that same path, so a retry always has an address to dial — and TryReconnect no-ops when it does not.
ClientState
The current local connection state (Stopped, Starting, Started, Stopping).
public LocalConnectionState ClientState { get; }
Property Value
- LocalConnectionState
ConnectionEstablishTimeoutSeconds
Timeout in seconds waiting for a new connection to reach Started state. Default 20.
public float ConnectionEstablishTimeoutSeconds { get; set; }
Property Value
ConnectionStopTimeoutSeconds
Timeout in seconds waiting for a connection to fully stop. Default 10.
public float ConnectionStopTimeoutSeconds { get; set; }
Property Value
CurrentConnectionType
The type of server currently connecting to (None, Login, World, Scene).
public ServerConnectionType CurrentConnectionType { get; set; }
Property Value
IsSceneHandoffReconnect
True when the reconnect currently armed or in progress was caused by a scene server deliberately handing the client back, rather than by a lost connection.
public bool IsSceneHandoffReconnect { get; }
Property Value
Remarks
A zone change, a channel switch and a cross-scene bind-point respawn are all implemented as a deliberate drop, so from the outside they are the same event as an outage: OnReconnectPending and OnReconnectAttempt fire for both. Anything that explains the wait to the player needs to tell them apart — labelling a routine teleport "connection lost" is worse than saying nothing at all.
Set alongside the shortened handoff backoff in FishMMO.Client.ClientConnectionManager.OnClientConnectionState(FishNet.Transporting.ClientConnectionStateArgs) and cleared once a connection is established, so it describes the wait that is actually running.
MaxReconnectAttempts
Maximum reconnect attempts before giving up. Range [1, 255]. Default 10.
public int MaxReconnectAttempts { get; set; }
Property Value
MaxReconnectDelay
Maximum delay in seconds for exponential backoff. Default 60.
public float MaxReconnectDelay { get; set; }
Property Value
NetworkManager
The FishNet NetworkManager managing this client connection.
public NetworkManager NetworkManager { get; }
Property Value
- NetworkManager
ReconnectAttemptWaitTime
Base wait time in seconds between reconnect attempts. Default 5.
public float ReconnectAttemptWaitTime { get; set; }
Property Value
ReconnectsAttempted
Number of reconnect attempts made since the last successful connection.
public int ReconnectsAttempted { get; }
Property Value
SceneHandoffReconnectDelay
Delay used for the first retry after a scene server hands the client back, instead of the full backoff. Jittered so a scene-wide event does not send every client at once.
public float SceneHandoffReconnectDelay { get; set; }
Property Value
Remarks
A scene-to-scene transfer is implemented as a deliberate drop: the scene server
releases the character and disconnects, and the client is expected to return to the
world server to be re-routed. That return went through the ordinary reconnect
backoff, so every teleport and channel switch cost a full
ReconnectAttemptWaitTime (5s) of dead time — during which the scene has
already unloaded and the loading overlay has already been dismissed by
OnSceneEndUnload, leaving the player looking at an empty world.
Only the first attempt is fast-pathed, and only from a Scene connection. If that attempt fails the normal exponential backoff resumes from attempt 1, so a genuinely unreachable world server is still not hammered.
Methods
CancelReconnect()
Cancels pending reconnect and fires OnReconnectFailed immediately.
public void CancelReconnect()
ConnectToServer(string, ushort, bool)
Initiates a connection. Guards against concurrent calls via CAS.
public void ConnectToServer(string address, ushort port, bool isWorldServer = false)
Parameters
addressstringServer IP or hostname.
portushortServer port.
isWorldServerboolIf true, stores address for reconnection logic.
ForceDisconnect()
Forces the connection closed and prevents auto-reconnect until reset.
public void ForceDisconnect()
Remarks
The suppression flag is only latched when there is a connection left to tear down. FishMMO.Client.ClientConnectionManager.OnClientConnectionState(FishNet.Transporting.ClientConnectionStateArgs) is what consumes it, so latching it against a connection that is already Stopped strands it: no further Stopped transition is raised to clear it, and the next ConnectToServer(string, ushort, bool) aborts inside OnAwaitingConnectionReady(string, ushort, bool) — silently, with the guard released and no connection started. The login screen reaches that state routinely, because every auth-error dialog calls this whether or not the transport is still up.
IsConnectionReady(bool)
Returns true if connected and optionally authenticated.
public bool IsConnectionReady(bool requireAuthentication = true)
Parameters
requireAuthenticationboolIf true, also checks connection is authenticated.
Returns
- bool
True if the connection is ready for use.
ResetReconnectState()
Resets all reconnect state: attempt count, connection type, stored address.
public void ResetReconnectState()
Shutdown()
Unsubscribes from NetworkManager events. Call during client teardown.
public void Shutdown()
TryReconnect()
Attempts a reconnect with exponential backoff. The backoff delay is set in FishMMO.Client.ClientConnectionManager.OnClientConnectionState(FishNet.Transporting.ClientConnectionStateArgs) when the connection stops and counted down in Update(). This method is called by Update() when the timer expires — it must NOT reset the delay or the reconnect will never fire.
public void TryReconnect()
Update()
Drives reconnect timer. Called every frame from the owning client.
public void Update()
Events
OnConnectionAttemptFailed
Fired when a non-reconnectable connection attempt fails (e.g. login server unreachable).
public event Action OnConnectionAttemptFailed
Event Type
OnConnectionSuccessful
Fired when a connection to the server is successfully established.
public event Action OnConnectionSuccessful
Event Type
OnReconnectAttempt
Fired on each reconnect attempt with current and max attempt counts.
public event Action<int, int> OnReconnectAttempt
Event Type
OnReconnectFailed
Fired when all reconnect attempts are exhausted without success.
public event Action OnReconnectFailed
Event Type
OnReconnectPending
Fired the moment a reconnect is armed, before the backoff delay begins.
public event Action OnReconnectPending
Event Type
Remarks
OnReconnectAttempt fires when the retry actually starts, which leaves the whole backoff window unreported. That window is not idle time during a scene transfer: the scene server has already unloaded the client's scene, so the loading overlay has been dismissed by the unload-end event and the player is looking at an empty world until the retry fires. Shortening the delay for a deliberate hop reduces that to a flicker; this event closes it, by letting the overlay treat "a reconnect is coming" as a transition in progress rather than waiting for it to begin.