using System; using Unity.Netcode; using UnityEngine; public enum RoundPhase : byte { WaitingForPlayers, WaitingForPlayersToLeave, WorkInProgress } [RequireComponent(typeof(NetworkObject))] public sealed class RoundGameLoopController : NetworkBehaviour { private readonly NetworkVariable phase = new( RoundPhase.WaitingForPlayers, NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Server); private StartRoomZone startRoom; public RoundPhase Phase => phase.Value; public event Action PhaseChanged; public override void OnNetworkSpawn() { phase.OnValueChanged += HandlePhaseChanged; startRoom = FindFirstObjectByType(); if (IsServer) phase.Value = RoundPhase.WaitingForPlayers; } public override void OnNetworkDespawn() { phase.OnValueChanged -= HandlePhaseChanged; } private void Update() { if (!IsServer) return; if (startRoom == null) startRoom = FindFirstObjectByType(); if (startRoom == null) return; switch (phase.Value) { case RoundPhase.WaitingForPlayers: if (AreAllPlayersInStartRoom()) phase.Value = RoundPhase.WaitingForPlayersToLeave; break; case RoundPhase.WaitingForPlayersToLeave: if (AreAllPlayersOutsideStartRoom()) phase.Value = RoundPhase.WorkInProgress; break; } } private bool AreAllPlayersInStartRoom() { if (!TryGetConnectedPlayers(out int playerCount)) return false; int playersInside = 0; foreach (NetworkClient client in NetworkManager.ConnectedClients.Values) { if (client.PlayerObject != null && startRoom.Contains(client.PlayerObject.transform.position)) playersInside++; } return playersInside == playerCount; } private bool AreAllPlayersOutsideStartRoom() { if (!TryGetConnectedPlayers(out int playerCount)) return false; int playersOutside = 0; foreach (NetworkClient client in NetworkManager.ConnectedClients.Values) { if (client.PlayerObject != null && !startRoom.Contains(client.PlayerObject.transform.position)) playersOutside++; } return playersOutside == playerCount; } private bool TryGetConnectedPlayers(out int playerCount) { playerCount = 0; if (NetworkManager == null || NetworkManager.ConnectedClients.Count == 0) return false; foreach (NetworkClient client in NetworkManager.ConnectedClients.Values) { if (client.PlayerObject == null) return false; playerCount++; } return playerCount > 0; } private void HandlePhaseChanged(RoundPhase _, RoundPhase current) => PhaseChanged?.Invoke(current); }