Table of Contents

Class Client

Namespace
FishMMO.Client
Assembly
FishMMO.Client.dll

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
Object
Component
Behaviour
MonoBehaviour
Client
Inherited Members
MonoBehaviour.IsInvoking()
MonoBehaviour.CancelInvoke()
MonoBehaviour.StopCoroutine(Coroutine)
MonoBehaviour.StopAllCoroutines()
MonoBehaviour.destroyCancellationToken
MonoBehaviour.useGUILayout
MonoBehaviour.didStart
MonoBehaviour.didAwake
MonoBehaviour.runInEditMode
Behaviour.enabled
Behaviour.isActiveAndEnabled
Component.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.transform
Component.transformHandle
Component.gameObject
Component.tag
Object.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.name
Object.hideFlags

Fields

MaximumTargetFrameRate

Absolute ceiling on the render rate, before the display's own limit is applied.

public const int MaximumTargetFrameRate = 500

Field Value

int

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

int

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

ClientPostbootSystem

Connection

Manages the client's connection lifecycle (connect, disconnect, reconnect).

public ClientConnectionManager Connection { get; }

Property Value

ClientConnectionManager

CurrentConnectionType

The current server connection type (None, Login, World, or Scene).

public ServerConnectionType CurrentConnectionType { get; }

Property Value

ServerConnectionType

LoadingSuppressed

Called when the local character starts. Sets up input controller and UI.

public static bool LoadingSuppressed { get; }

Property Value

bool

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

ClientLoginAuthenticator

LoginServerPorts

Cached list of login server addresses discovered via API host probing.

public List<ushort> LoginServerPorts { get; }

Property Value

List<ushort>

LoginServerRequestTimeoutSeconds

Timeout in seconds for each login server probe request.

public int LoginServerRequestTimeoutSeconds { get; }

Property Value

int

WorldPreloadScenes

List of addressable scenes to preload when entering the game world.

public List<AddressableSceneLoadData> WorldPreloadScenes { get; }

Property Value

List<AddressableSceneLoadData>

Methods

ApplyTargetFrameRate(int)

Caps how fast the client renders.

public static void ApplyTargetFrameRate(int framesPerSecond)

Parameters

framesPerSecond int

Target 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

broadcast T

The broadcast message to send.

channel Channel

The network channel to use (default Reliable).

Type Parameters

T

The 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

port ushort

The server port.

isWorldServer bool

If true, marks this as a world server connection.

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

suppress bool

True 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

onFail Action<string>

Callback invoked with an error message if all probes fail.

onDone Action<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

state LocalConnectionState

The connection state to check for.

requireAuth bool

If 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

requireAuth bool

If 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

forceDisconnect bool

If 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

port ushort
isWorldServer bool

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

port ushort

Returns

bool

True if an address was available; otherwise, false.

Events

OnConnectionSuccessful

Forwarded to OnConnectionSuccessful.

public event Action OnConnectionSuccessful

Event Type

Action

OnEnterGameWorld

Invoked when the client has successfully entered the game world after scene login.

public event Action OnEnterGameWorld

Event Type

Action

OnQuitToLogin

Invoked when the client transitions from the game world back to the login screen.

public event Action OnQuitToLogin

Event Type

Action

OnReconnectAttempt

Forwarded to OnReconnectAttempt.

public event Action<int, int> OnReconnectAttempt

Event Type

Action<int, int>

OnReconnectFailed

Forwarded to OnReconnectFailed.

public event Action OnReconnectFailed

Event Type

Action

OnReconnectPending

Forwarded to OnReconnectPending.

public event Action OnReconnectPending

Event Type

Action