using UnityEngine; /// /// Placeholder on-screen match HUD: the current sub-phase + countdown (top centre) and a hunter crosshair /// during the seek phase. Drawn with IMGUI (OnGUI) on purpose - it needs no Canvas / font asset authoring, /// so the match-state logic can be exercised immediately; swap it for a proper uGUI canvas once the look is /// finalised. Added at runtime by (AddComponent), so it rides the persistent /// manager object and reads on every machine. /// [DisallowMultipleComponent] public class MatchHud : MonoBehaviour { private GUIStyle _phaseStyle; private GUIStyle _timeStyle; private void OnGUI() { var match = MatchManager.Instance; if (!match || !match.MatchActive) return; EnsureStyles(); const float w = 360f; var phaseRect = new Rect((Screen.width - w) * 0.5f, 12f, w, 30f); var timeRect = new Rect(phaseRect.x, phaseRect.y + 28f, w, 36f); DrawShadowed(phaseRect, PhaseLabel(match.LocalSubPhase), _phaseStyle); DrawShadowed(timeRect, FormatTime(match.LocalPhaseRemaining), _timeStyle); if (match.LocalSubPhase == MatchManager.MatchSubPhase.Seek && LocalIsHunter()) DrawCrosshair(); } private static string PhaseLabel(MatchManager.MatchSubPhase phase) { switch (phase) { case MatchManager.MatchSubPhase.Hide: return "Verstecken"; case MatchManager.MatchSubPhase.Seek: return "Suchen"; case MatchManager.MatchSubPhase.Resolution: return "Auflösung"; default: return ""; } } private static string FormatTime(float seconds) { int s = Mathf.CeilToInt(Mathf.Max(0f, seconds)); return $"{s / 60:0}:{s % 60:00}"; } private static bool LocalIsHunter() { var nm = Unity.Netcode.NetworkManager.Singleton; if (!nm || nm.LocalClient == null) return false; var po = nm.LocalClient.PlayerObject; if (!po) return false; var setup = po.GetComponent(); return setup && setup.ScopedModes && setup.Role == PlayerRole.Hunter; } private static void DrawCrosshair() { float cx = Screen.width * 0.5f; float cy = Screen.height * 0.5f; const float r = 8f, t = 2f; Color prev = GUI.color; GUI.color = new Color(1f, 1f, 1f, 0.85f); GUI.DrawTexture(new Rect(cx - r, cy - t * 0.5f, r * 2f, t), Texture2D.whiteTexture); GUI.DrawTexture(new Rect(cx - t * 0.5f, cy - r, t, r * 2f), Texture2D.whiteTexture); GUI.color = prev; } // One label drawn twice (dark offset behind, then the real colour) so it stays readable on any backdrop. private static void DrawShadowed(Rect r, string text, GUIStyle style) { if (string.IsNullOrEmpty(text)) return; Color real = style.normal.textColor; style.normal.textColor = new Color(0f, 0f, 0f, 0.7f); GUI.Label(new Rect(r.x + 1f, r.y + 1f, r.width, r.height), text, style); style.normal.textColor = real; GUI.Label(r, text, style); } private void EnsureStyles() { if (_phaseStyle == null) { _phaseStyle = new GUIStyle(GUI.skin.label) { alignment = TextAnchor.MiddleCenter, fontSize = 22, fontStyle = FontStyle.Bold, }; _phaseStyle.normal.textColor = Color.white; } if (_timeStyle == null) { _timeStyle = new GUIStyle(GUI.skin.label) { alignment = TextAnchor.MiddleCenter, fontSize = 28, fontStyle = FontStyle.Bold, }; _timeStyle.normal.textColor = Color.white; } } }