📂 Prerequisites & Folder Layout
Organize your project:
/Assets/
/Scripts/
StartupUIManager.cs
CustomNetworkManager.cs
NetworkPlayer.cs
PlayerLobbyUIEntry.cs
GameplayPlayer.cs
GameplayPlayerUIEntry.cs
GameplayUIManager.cs
/Prefabs/
NetworkPlayer.prefab
PlayerLobbyUIEntry.prefab
GameplayPlayer.prefab
GameplayPlayerUIEntry.prefab
/Scenes/
Splash.unity
MainMenu.unity
Lobby.unity
Gameplay.unity
1️⃣ Startup & Main Menu (StartupUIManager.cs
)
- 🎯 Purpose: Collect IP, port & player name → Start Host/Client.
- 🔧 Inspector:
addressField
, portField
, userName
, hostButton
, joinButton
.
- 🚀 Host:
SetPlayerName();
ApplyNetworkPort();
NetworkManager.singleton.StartHost();
- 🚪 Join:
SetPlayerName();
ApplyNetworkPort();
NetworkManager.singleton.networkAddress = addressField.text;
NetworkManager.singleton.StartClient();
Wire up: Add three TMP InputFields + two Buttons to your Canvas and assign them in the Inspector.
2️⃣ Network Flow & Scene Management (CustomNetworkManager.cs
)
- 🎯 Purpose: Persistent lobby player → swap in-game avatars on scene change.
- 🔍 Awake: Caches short names for `onlineScene` (Lobby) & `gameplayScenePath` (Gameplay).
- 🖥️ OnStartHost: Mirror auto-loads Lobby.
- 🔌 OnClientConnect: Sends `Ready()` + `AddPlayer()`.
- ✨ OnServerAddPlayer: Instantiates your `networkPlayerPrefab`.
- 🔄 OnServerSceneChanged:
- 🏠 Lobby: Respawns missing `NetworkPlayer` when returning.
- 🎮 Gameplay: `NetworkServer.Spawn(gameplayPlayerPrefab, conn)` for each player.
- ▶️ StartGameplayScene() & ReturnToLobbyScene(): server-only scene switches.
Wire up: In Splash scene, add `CustomNetworkManager`, assign your scenes + prefabs in the Inspector.
3️⃣ Persistent Player Data (NetworkPlayer.cs
)
- 🎯 Purpose: Sync name, ready/host flags, ping; spawn lobby UI rows.
- 🔗 SyncVars: `playerName`, `isReady`, `isHost`, `pingMs` (with hooks).
- 🚀 OnStartLocalPlayer: `CmdInitProfile(...)` sets initial name & host flag.
- ⏱️ Update(): Every second measures `NetworkTime.rtt` → `CmdReportPing()` to sync `pingMs`.
- 📋 Scene-watch: On lobby load → spawn/destroy a UI row via coroutine.
- 📜 Commands:
CmdToggleReady()
, CmdStartGame()
, CmdReturnToLobby()
.
Wire up: Create `NetworkPlayer.prefab` with a `NetworkIdentity` + this script; assign `lobbyRowPrefab`.
4️⃣ Lobby UI Row (PlayerLobbyUIEntry.cs
)
- 🎯 Purpose: One row in your Lobby list showing name, ✔ tick, host icon & a button.
- 🔗 Bind(NetworkPlayer): Wires the row, sets name, icon color.
- 🔄 Refresh(): Called on SyncVar hooks to update visuals.
- 🔘 Buttons:
- **Start** if you’re host → `CmdStartGame()`
- **Ready** if you’re client → `CmdToggleReady()`
Wire up: Build a prefab with `TMP_Text`, `Image`, `Button`, attach this script, then assign it in `NetworkPlayer`.
5️⃣ Gameplay UI & Rows
a) GameplayPlayer (GameplayPlayer.cs
)
A minimal network avatar in the Gameplay scene with just a synced `playerName`.
b) GameplayPlayerUIEntry (GameplayPlayerUIEntry.cs
)
- 🎯 Bind(NetworkPlayer): Sets player name on the row.
- 🎨 UpdatePingDisplay(int): Recolors a ping icon based on `pingMs`.
- ⏳ Fallback: Can use `NetworkTime.rtt` in `Update()` for quick tests.
c) GameplayUIManager (GameplayUIManager.cs
)
- 🔍 Start(): Waits for the local player → calls `Init()`.
- 🚪 Init(): Shows **Back to Lobby** for host + wires it to `CmdReturnToLobby()`.
- 📋 BuildPlayerList(): Instantiates a row for each `NetworkPlayer` found in scene.
- 📡 UpdatePingFor(NetworkPlayer): Static hook updates a single row’s ping icon when `pingMs` changes.
Wire up: In your Gameplay Canvas assign `backToLobbyBtn`, `playerListParent`, and `playerEntryPrefab`.
🚀 Running & Extending
- 🔨 Build & Run two instances:
- Host: Main Menu → Start Host → see yourself in Lobby
- Client: Enter IP + port → Join → appear in Lobby
- ✅ Client “Ready” + Host “Start” → everyone loads Gameplay
- 🔙 “Back to Lobby” returns all players cleanly
💡 Pro Tips & Next Steps
- 🔑 Add a lobby password in `StartupUIManager`
- 📜 Document everything in a
README.md
for GitHub & itch.io
- 🎨 Polish UI: consistent fonts, colors, animations
- 🌐 Test Internet play: router port-forwarding & firewall
- ⚔️ Next Project: drop this shell into your roguelike to handle networking