Skip to content

Networking Architecture

the-real-ltcg edited this page Jul 19, 2026 · 1 revision

Networking Architecture

Multiplayer runs on Unity Netcode for GameObjects (NGO), transported over UnityTransport (raw UDP/IP, no relay or lobby service configured).

Session setup (NetworkUI.cs)

  • Host button: calls NetworkManager.Singleton.StartHost(). The host is both the authoritative server and a client. It looks up and displays its own local IPv4 address so others know what to connect to.
  • Client button: reveals an IP input (pre-filled with your own subnet, e.g. 192.168.1.) and a Connect button.
  • Connect: sets the transport's connection data to the typed IP on port 7777, then calls StartClient().

Because this is a bare UnityTransport setup, all players must be reachable on the same LAN — there's no NAT traversal or relay yet. Adding Unity Relay would be the natural next step for internet play.

Player movement sync

Movement/animation use custom ClientNetworkTransform / ClientNetworkAnimator (in Assets/Scripts/) instead of NGO's stock components — these make movement client-authoritative (the owning client's Transform/Animator drives the sync) rather than server-authoritative, which fits a fast local-play game better than it would a competitive/cheat-resistant one.

Dart throwing flow

  1. Owning client presses TDartController (in PlayerShoot.cs) calls ShootProjectileServerRpc().
  2. Server instantiates the Dart_V1 prefab, gives it velocity, and spawns it as a NetworkObject with ownership assigned back to the throwing client (SpawnWithOwnership).
  3. The dart replicates to all clients as a normal networked object.

Tag/freeze flow

  1. Projectile.cs's OnCollisionEnter only runs its logic on the server (if (!IsServer) return).
  2. If the dart hit an object tagged "Player", the server calls ThirdPersonController.TagPlayerServerRpc(true) on that player.
  3. That RPC forwards to TagPlayerClientRpc(true), setting _isTagged = true on every client — this zeroes the tagged player's move speed in Move() (they can still look around, just not walk/run).
  4. Separately, ThirdPersonController.OnCollisionEnter (server-only) detects two players colliding and calls TagPlayerServerRpc(false) on the one that was hit — that's the "bump to unfreeze" mechanic.
  5. The dart itself zeroes its velocity on impact and tells all clients to destroy it after a short delay (DestroyProjectileClientRpc).

Player identity

ColorController.cs gives each player a random color on spawn (NetworkVariable<Color>, server-authoritative value, broadcast to all clients), rerollable with C. This is currently the only per-player visual differentiator — there's no player name/tag UI yet.

Clone this wiki locally