Sweep over 48 files (Editor/ excluded): remove comments that restate the code, condense class summaries, fix three stale doc statements (HsvColorPicker alpha bar, PaintHud layoutPrefab, MasterVolume FallbackDefault). Inline two single-use wrappers (IsPointerOverUi, BuildModes), drop an unused using, replace a magic literal with the existing ParallaxBase constant, and convert ~10 UnityEngine.Object null checks to the implicit-bool convention. No serialized fields, signatures, RPC/NetworkVariable names, defaults, or #if blocks touched. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
112 lines
4.3 KiB
C#
112 lines
4.3 KiB
C#
using TMPro;
|
|
using UnityEngine;
|
|
|
|
/// <summary>
|
|
/// Binds the authored <c>MatchHudCanvas</c> widgets to live match state (sub-phase + countdowns, role
|
|
/// counts, hunter crosshair); creates nothing at runtime. Passive overlay: the canvas has no
|
|
/// <see cref="UnityEngine.UI.GraphicRaycaster"/> and every graphic is raycastTarget=false, and its
|
|
/// sortingOrder (90) sits below PaintHud's (100) so tool panels always win. There is no change event for
|
|
/// the phase/timer, so values are polled per frame; the visible strings are only rebuilt when the
|
|
/// displayed second / phase actually changes.
|
|
/// </summary>
|
|
[DisallowMultipleComponent]
|
|
public class MatchHud : MonoBehaviour
|
|
{
|
|
[Tooltip("HUD canvas, toggled with the match. Empty = the Canvas on this GameObject.")]
|
|
[SerializeField] private Canvas _canvas;
|
|
|
|
[Tooltip("Sub-phase label in the top bar.")]
|
|
[SerializeField] private TMP_Text _phaseText;
|
|
|
|
[Tooltip("Countdown label in the top bar.")]
|
|
[SerializeField] private TMP_Text _timeText;
|
|
|
|
[Tooltip("Seconds until the next radar ping sweep; counts down from the interval and repeats. Shown only " +
|
|
"during the seek phase (blank otherwise).")]
|
|
[SerializeField] private TMP_Text _pingTimeText;
|
|
|
|
[SerializeField] private TMP_Text _hunterCount;
|
|
[SerializeField] private TMP_Text _hiderCount;
|
|
|
|
[Tooltip("Crosshair, shown only for the hunter during the seek phase.")]
|
|
[SerializeField] private GameObject _crosshair;
|
|
|
|
private int _lastSecond = -1;
|
|
private int _lastPingSecond = -1;
|
|
private int _lastHunters = -1;
|
|
private int _lastHiders = -1;
|
|
private MatchManager.MatchSubPhase _lastPhase = (MatchManager.MatchSubPhase)(-1);
|
|
|
|
private void Awake()
|
|
{
|
|
if (!_canvas) _canvas = GetComponent<Canvas>();
|
|
if (!_canvas || !_phaseText || !_timeText || !_pingTimeText || !_crosshair || !_hunterCount || !_hiderCount)
|
|
{
|
|
Debug.LogError("[MatchHud] Unwired reference(s) - assign Canvas/Phase/Time/PingTime/Crosshair/HunterCount/HiderCount in the Inspector.", this);
|
|
enabled = false;
|
|
return;
|
|
}
|
|
|
|
// Toggling the Canvas component (not the GameObject) keeps this binder's Update alive while hidden.
|
|
_canvas.enabled = false; // shown once a match is active
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
var match = MatchManager.Instance;
|
|
bool active = match && match.MatchActive;
|
|
if (_canvas.enabled != active) _canvas.enabled = active;
|
|
if (!active) return;
|
|
|
|
var phase = match.LocalSubPhase;
|
|
if (phase != _lastPhase)
|
|
{
|
|
_lastPhase = phase;
|
|
_phaseText.text = PhaseLabel(phase);
|
|
}
|
|
|
|
int s = Mathf.CeilToInt(Mathf.Max(0f, match.LocalPhaseRemaining));
|
|
if (s != _lastSecond)
|
|
{
|
|
_lastSecond = s;
|
|
_timeText.text = $"{s / 60:0}:{s % 60:00}";
|
|
}
|
|
|
|
// Next-radar-sweep countdown: shown for everyone during Seek (pings only fire then), 0:00 otherwise.
|
|
bool showPing = phase == MatchManager.MatchSubPhase.Seek && match.RadarPingInterval > 0f;
|
|
int p = showPing ? Mathf.CeilToInt(Mathf.Max(0f, match.LocalNextPingIn)) : 0;
|
|
if (p != _lastPingSecond)
|
|
{
|
|
_lastPingSecond = p;
|
|
_pingTimeText.text = $"{p / 60:0}:{p % 60:00}";
|
|
}
|
|
|
|
NetworkPlayerSetup.CountRoles(out int hunters, out int hiders);
|
|
if (hunters != _lastHunters)
|
|
{
|
|
_lastHunters = hunters;
|
|
_hunterCount.text = hunters.ToString();
|
|
}
|
|
if (hiders != _lastHiders)
|
|
{
|
|
_lastHiders = hiders;
|
|
_hiderCount.text = hiders.ToString();
|
|
}
|
|
|
|
bool showCross = phase == MatchManager.MatchSubPhase.Seek && NetworkPlayerSetup.LocalViewerIsHunter();
|
|
if (_crosshair.activeSelf != showCross) _crosshair.SetActive(showCross);
|
|
}
|
|
|
|
private static string PhaseLabel(MatchManager.MatchSubPhase phase)
|
|
{
|
|
switch (phase)
|
|
{
|
|
case MatchManager.MatchSubPhase.Loading: return "Loading";
|
|
case MatchManager.MatchSubPhase.Hide: return "Hide";
|
|
case MatchManager.MatchSubPhase.Seek: return "Seek";
|
|
case MatchManager.MatchSubPhase.Resolution: return "Resolution";
|
|
default: return "";
|
|
}
|
|
}
|
|
}
|