Class Client
Thin orchestrator for the client. Delegates connection lifecycle to ClientConnectionManager, combat display to ClientCombatDisplay, and fog to ClientFogManager. Handles login server discovery and character lifecycle events that must live on the root GameObject.
public class Client : MonoBehaviour
- Inheritance
-
ObjectComponentBehaviourMonoBehaviourClient
- Inherited Members
-
MonoBehaviour.IsInvoking()MonoBehaviour.CancelInvoke()MonoBehaviour.StopCoroutine(Coroutine)MonoBehaviour.StopAllCoroutines()MonoBehaviour.destroyCancellationTokenMonoBehaviour.useGUILayoutMonoBehaviour.didStartMonoBehaviour.didAwakeMonoBehaviour.runInEditModeBehaviour.enabledBehaviour.isActiveAndEnabledComponent.GetComponent<T>()Component.TryGetComponent<T>(out T)Component.GetComponentInChildren<T>()Component.GetComponentsInChildren<T>()Component.GetComponentInParent<T>()Component.GetComponentsInParent<T>()Component.GetComponents<T>()Component.GetComponentIndex()Component.CompareTag(TagHandle)Component.transformComponent.transformHandleComponent.gameObjectComponent.tagObject.GetEntityId()Object.GetInstanceID()Object.GetHashCode()Object.InstantiateAsync<T>(T)Object.InstantiateAsync<T>(T, Transform)Object.InstantiateAsync<T>(T, Vector3, Quaternion)Object.InstantiateAsync<T>(T, Transform, Vector3, Quaternion)Object.Instantiate(Object, Vector3, Quaternion)Object.Instantiate(Object, Vector3, Quaternion, Transform)Object.Instantiate(Object)Object.Instantiate(Object, Scene)Object.Instantiate<T>(T, InstantiateParameters)Object.Instantiate<T>(T, Vector3, Quaternion, InstantiateParameters)Object.Instantiate(Object, Transform)Object.Instantiate<T>(T)Object.Instantiate<T>(T, Vector3, Quaternion)Object.Instantiate<T>(T, Vector3, Quaternion, Transform)Object.Instantiate<T>(T, Transform)Object.Destroy(Object)Object.DestroyImmediate(Object)Object.DontDestroyOnLoad(Object)Object.DestroyObject(Object)Object.FindObjectsOfType<T>()Object.FindObjectsByType<T>(FindObjectsSortMode)Object.FindObjectsByType<T>(FindObjectsInactive, FindObjectsSortMode)Object.FindObjectOfType<T>()Object.FindFirstObjectByType<T>()Object.FindAnyObjectByType<T>()Object.FindFirstObjectByType<T>(FindObjectsInactive)Object.FindAnyObjectByType<T>(FindObjectsInactive)Object.FindObjectsByType<T>()Object.FindObjectsByType<T>(FindObjectsInactive)Object.ToString()Object.nameObject.hideFlags
Fields
MaximumTargetFrameRate
Absolute ceiling on the render rate, before the display's own limit is applied.
public const int MaximumTargetFrameRate = 500
Field Value
Remarks
500 is also FishNet's own NetworkManager.MAXIMUM_FRAMERATE, which
ClientManager.SetFrameRate clamps to. Matching it means the two never disagree
about what was requested. The effective ceiling is normally lower — see
ResolveMaximumFrameRate().
MinimumTargetFrameRate
Lowest render rate a client may be capped to.
public const int MinimumTargetFrameRate = 30
Field Value
Remarks
The floor exists because of the tick, not because of visual quality. FishNet derives ticks from the update loop, so a frame rate below the tick rate cannot deliver them on time: ticks bunch up several to a frame and the client falls behind the server's timeline. 30 matches the project's tick rate, and ResolveMinimumFrameRate() raises it automatically if the tick rate is ever increased.
NetworkManager
Reference to the FishNet NetworkManager singleton used by all client networking.
public static NetworkManager NetworkManager
Field Value
- NetworkManager
Properties
AudioListener
AudioListener component used by the client for 3D audio positioning.
public AudioListener AudioListener { get; }
Property Value
- AudioListener
ClientPostbootSystem
Optional post-boot system for client-side initialization after scene load.
public ClientPostbootSystem ClientPostbootSystem { get; }
Property Value
Connection
Manages the client's connection lifecycle (connect, disconnect, reconnect).
public ClientConnectionManager Connection { get; }
Property Value
CurrentConnectionType
The current server connection type (None, Login, World, or Scene).
public ServerConnectionType CurrentConnectionType { get; }
Property Value
LoadingSuppressed
Called when the local character starts. Sets up input controller and UI.
public static bool LoadingSuppressed { get; }
Property Value
Remarks
This deliberately does not suppress genuine scene transitions. The overlay has
two independent drivers: AddressableLoadProcessor.OnProgressUpdate, which
fires for any background asset work and would otherwise flash the overlay over
live gameplay, and FishNet's SceneManager load events, which are real zone
changes the player must see a loading screen for.
Gating both on this flag meant that once it latched — which happened at the network handshake, before the first scene had even loaded — no loading screen could ever appear again for the rest of the session, including zone-to-zone teleports. The flag is now checked only on the Addressable path.
LoginAuthenticator
Authenticator used for login and world server authentication.
public ClientLoginAuthenticator LoginAuthenticator { get; }
Property Value
LoginServerPorts
Cached list of login server addresses discovered via API host probing.
public List<ushort> LoginServerPorts { get; }
Property Value
LoginServerRequestTimeoutSeconds
Timeout in seconds for each login server probe request.
public int LoginServerRequestTimeoutSeconds { get; }
Property Value
WorldPreloadScenes
List of addressable scenes to preload when entering the game world.
public List<AddressableSceneLoadData> WorldPreloadScenes { get; }
Property Value
Methods
ApplyTargetFrameRate(int)
Caps how fast the client renders.
public static void ApplyTargetFrameRate(int framesPerSecond)
Parameters
framesPerSecondintTarget frames per second, normally the user's saved frame-rate preference. Clamped between ResolveMinimumFrameRate() and ResolveMaximumFrameRate() — that is, no slower than the tick rate and no faster than the display can present.
Remarks
Render rate and tick rate are independent. This sets only how often the client
draws. Simulation runs on the FishNet TimeManager tick — a fixed 30 Hz, set
per-scene and identical on client and server — and every authoritative system rides it:
prediction, reconciliation, cooldowns, ability activation and NPC brains. A player at
500 FPS and one at 30 FPS send the same number of packets, simulate the same number of
physics steps, and reconcile against the same ticks. The only things a higher frame rate
buys are smoother interpolation between ticks and slightly fresher input sampling
within one.
The single point where the two touch is the floor above: the frame rate must clear the tick rate for ticks to be delivered on schedule. That is a one-way dependency — the tick rate is never derived from the render rate.
Clamped rather than rejected. The previous version returned without doing anything for an out-of-range value, so a monitor reporting an unusual refresh rate left the cap at whatever it happened to be — silently ignoring the user's setting instead of honouring it as closely as it can.
Setting UnityEngine.Application.targetFrameRate alone is not reliably enough. FishNet's
NetworkManager.UpdateFramerate writes targetFrameRate from
ClientManager.FrameRate every time the connection state changes, so a value set
here can be discarded at the next connect or server hop. The client scene now ships with
ChangeFrameRate disabled so FishNet leaves the render rate alone entirely, but
the matching ClientManager.SetFrameRate call below is kept: it costs nothing, and
it keeps the preference intact if the flag is ever re-enabled or the client runs as a
host, where FishNet takes the higher of the client and server rates.
Applying the screen refresh rate via Screen.SetResolution changes the
display mode only; with vSync off it does not limit the render loop.
Broadcast<T>(T, Channel)
Sends a network broadcast to the server on the specified channel.
public static void Broadcast<T>(T broadcast, Channel channel = Channel.Reliable) where T : struct, IBroadcast
Parameters
broadcastTThe broadcast message to send.
channelChannelThe network channel to use (default Reliable).
Type Parameters
TThe broadcast message type.
ConnectToServer(ushort, bool)
Connects the client to a game server at the specified port. Hostname is always GameHost. With WebTransport, the port is a QUIC connection parameter, not a URL path.
public void ConnectToServer(ushort port, bool isWorldServer = false)
Parameters
DismissLoadingScreen(bool)
Hides the loading overlay and optionally suppresses future incidental re-shows. Called on local character start, when the player actually exists in the world.
public static void DismissLoadingScreen(bool suppress)
Parameters
suppressboolTrue to stop background asset loads from re-showing the overlay. Genuine scene transitions are unaffected — see LoadingSuppressed.
ForceDisconnect()
Forces an immediate disconnection from the current server.
public void ForceDisconnect()
GetLoginServerList(Action<string>, Action<List<ushort>, string>)
Probes API host candidates for a login server address list and the connection token that must accompany the next handshake. Always performs a fresh probe.
public IEnumerator GetLoginServerList(Action<string> onFail, Action<List<ushort>, string> onDone)
Parameters
onFailAction<string>Callback invoked with an error message if all probes fail.
onDoneAction<List<ushort>, string>Callback invoked with the list of discovered server addresses.
Returns
- IEnumerator
Coroutine enumerator.
Remarks
This deliberately does not cache. IPFetch returns the port list and the connection token in one response, the token is single-use, and every connect needs one — so a cache hit could never skip the round trip it would have to make anyway to mint a fresh token. A TTL-based port cache used to sit here; it was unreachable, because its guard required an unspent FishMMO.Client.Client.cachedConnectionToken and FishMMO.Client.Client.TakeConnectionToken() clears that on the same synchronous path that sets it. Serving a stale list with a spent or expired token would present as a silent login failure that only a client restart clears, so re-probing is also the safe behaviour, not merely the simpler one.
Initialize()
Initializes NetworkManager, authenticator, transport, audio, UI, and event handlers. This starts the primary client behaviour.
public void Initialize()
IsConnectionReady(LocalConnectionState, bool)
Checks whether the client connection is in the specified state and ready. Backward-compatible overload accepting LocalConnectionState.
public bool IsConnectionReady(LocalConnectionState state, bool requireAuth = false)
Parameters
stateLocalConnectionStateThe connection state to check for.
requireAuthboolIf true, the connection must be authenticated to be considered ready.
Returns
- bool
True if the connection is in the specified state and ready; otherwise, false.
IsConnectionReady(bool)
Checks whether the client connection is ready (authenticated by default).
public bool IsConnectionReady(bool requireAuth = true)
Parameters
requireAuthboolIf true, the connection must be authenticated to be considered ready.
Returns
- bool
True if the connection is ready; otherwise, false.
Quit()
Exits the application (play mode in editor, Application.Quit in builds, or WebGL key-hijack path).
public void Quit()
QuitToLogin(bool)
Disconnects from the game world and returns to the login screen.
public void QuitToLogin(bool forceDisconnect = true)
Parameters
forceDisconnectboolIf true, forces an immediate disconnection.
ReconnectCancel()
Cancels any active reconnection attempt.
public void ReconnectCancel()
RequestHopTokenThenConnect(ushort, bool)
Asks the currently connected server for a connection token, then connects to
port once it arrives (or the wait times out).
public void RequestHopTokenThenConnect(ushort port, bool isWorldServer)
Parameters
Remarks
Used for both server hops — Login → World and World → Scene. The token must be obtained before the current connection is torn down, because it is the only party that knows this client's real IP; that is why it cannot be fetched from inside the connect coroutine, which runs after StopConnection.
ResolveDisplayRefreshRate()
The fastest refresh rate the current display reports.
public static int ResolveDisplayRefreshRate()
Returns
- int
The highest reported refresh rate in hertz, or a safe fallback.
Remarks
Scans every supported display mode rather than reading the current one: a player running windowed at a lower mode still has the panel's full refresh rate available, and capping them to whatever mode they happen to be in would be wrong.
ResolveMaximumFrameRate()
The highest frame rate this client may be capped to: the monitor's fastest mode, or MaximumTargetFrameRate, whichever is lower.
public static int ResolveMaximumFrameRate()
Returns
- int
The maximum frames per second.
Remarks
Frames drawn faster than the display can present them are never seen. They cost GPU time, power and heat to produce and are then discarded at scan-out, so the ceiling is the panel's own capability rather than an arbitrary number.
Enforced here rather than only in the options UI so the bound holds for every caller — a saved preference from a machine with a faster monitor, or a config edited by hand, clamps down to what the current display can actually show.
The 500 ceiling still applies on top, both because it is FishNet's own limit and because a display reporting something implausible should not be taken at its word.
ResolveMinimumFrameRate()
The lowest frame rate this client may be capped to, given the live tick rate.
public static int ResolveMinimumFrameRate()
Returns
- int
The minimum frames per second.
Remarks
Reads the tick rate from the TimeManager when one exists so the floor tracks the actual configuration rather than a constant that can drift away from it. Falls back to MinimumTargetFrameRate before the network is up.
RestoreLoadingScreen()
Re-arms the incidental loading overlay after leaving the world.
public static void RestoreLoadingScreen()
Remarks
LoadingSuppressed latches on world entry and had no counterpart, so it stayed set for the rest of the process: quit to login and come back and the Addressable-driven overlay never appeared again, because both loading screens return early from their progress handler while it is set. Clearing it on the way out of the world restores the overlay for the next login/world-entry cycle.
TryGetRandomLoginServerPort(out ushort)
Attempts to retrieve a random login server address from the cached list.
public bool TryGetRandomLoginServerPort(out ushort port)
Parameters
portushort
Returns
- bool
True if an address was available; otherwise, false.
Events
OnConnectionSuccessful
Forwarded to OnConnectionSuccessful.
public event Action OnConnectionSuccessful
Event Type
OnEnterGameWorld
Invoked when the client has successfully entered the game world after scene login.
public event Action OnEnterGameWorld
Event Type
OnQuitToLogin
Invoked when the client transitions from the game world back to the login screen.
public event Action OnQuitToLogin
Event Type
OnReconnectAttempt
Forwarded to OnReconnectAttempt.
public event Action<int, int> OnReconnectAttempt
Event Type
OnReconnectFailed
Forwarded to OnReconnectFailed.
public event Action OnReconnectFailed
Event Type
OnReconnectPending
Forwarded to OnReconnectPending.
public event Action OnReconnectPending