Unity NetworkLobbyManager中协程自行终止问题排查
Let's break down why your coroutine is stopping early and walk through solutions to get it working as intended.
Common Causes of the Coroutine Stopping
Your coroutine likely terminates abruptly due to one of these issues:
- Null Reference Exception: If
LobbyDiscovery.singletonbecomesnullwhile the coroutine runs, accessingnetworkIpAddrwill throw an uncaught exception, killing the coroutine immediately. - Host Object Destruction: If the
NetworkLobbyManagerinstance running the coroutine gets disabled or destroyed mid-execution, all its running coroutines will stop. - Unintended IP Value: It's possible
networkIpAddris being set to an empty string again after an initial change, but your current loop only checks for an empty string—though this would make the loop restart, not terminate.
Step-by-Step Fixes
1. Add Null Checks & Error Handling to the Coroutine
First, update your coroutine to handle potential null references and log clearer info to debug what's happening:
IEnumerator CheckIPAddressAvailability() { // Loop until we have a valid LobbyDiscovery instance and non-empty IP while (LobbyDiscovery.singleton == null || string.IsNullOrEmpty(LobbyDiscovery.singleton.networkIpAddr)) { if (LobbyDiscovery.singleton != null) { Debug.Log($"Waiting for IP address... Current value: {LobbyDiscovery.singleton.networkIpAddr}"); } else { Debug.Log("LobbyDiscovery singleton not found yet—waiting for initialization..."); } yield return null; // Wait one frame before checking again } gotIpAddr(); }
This prevents null reference crashes and gives you visibility into why the loop is running (or stopping).
2. Ensure the Coroutine Runs on a Persistent Object
Make sure your NetworkLobbyManager instance isn't destroyed during the process. Add this to its Awake() method to keep it alive across scenes:
private void Awake() { DontDestroyOnLoad(gameObject); }
Also, double-check that you're starting the coroutine correctly from an active object:
public void OnJoinButtonClicked() { // Only start the coroutine if the manager is active and valid if (this != null && isActiveAndEnabled) { StartCoroutine(CheckIPAddressAvailability()); } }
3. Switch to Event-Driven Logic (More Robust Alternative)
Instead of polling with a coroutine, use an event in LobbyDiscovery to trigger your gotIpAddr() method when the IP is ready. This avoids loop-related issues entirely:
Update LobbyDiscovery:
using UnityEngine.Events; public class LobbyDiscovery : /* your base class */ { // Event triggered when a valid IP address is received public event Action<string> OnValidIpReceived; private string _networkIpAddr; public string networkIpAddr { get => _networkIpAddr; set { _networkIpAddr = value; // Trigger the event only if the IP is non-empty if (!string.IsNullOrEmpty(value)) { OnValidIpReceived?.Invoke(value); } } } // ... rest of your LobbyDiscovery code }
Update Your NetworkLobbyManager:
public void OnJoinButtonClicked() { if (LobbyDiscovery.singleton == null) { Debug.LogError("LobbyDiscovery singleton not available!"); return; } // If IP is already available, run gotIpAddr() immediately if (!string.IsNullOrEmpty(LobbyDiscovery.singleton.networkIpAddr)) { gotIpAddr(); } else { // Subscribe to the event to wait for the IP LobbyDiscovery.singleton.OnValidIpReceived += HandleIpReceived; } } private void HandleIpReceived(string ipAddress) { gotIpAddr(); // Unsubscribe to prevent memory leaks if (LobbyDiscovery.singleton != null) { LobbyDiscovery.singleton.OnValidIpReceived -= HandleIpReceived; } }
This approach is more efficient and avoids the risks of coroutine termination due to object state changes.
内容的提问来源于stack exchange,提问作者Saeesh Tendulkar

