using System.Collections.Generic;
using UnityEngine;
///
/// Sits on the "Radar" overlay object (a disc rendered by the Radar Camera in front of the main camera).
/// Spawns "Target" blips - clones of the child "Target Template" - each of which continuously points from
/// the reference camera toward a world-space transform (visualising the bearing camera -> target) and then
/// destroys itself after a given lifetime. See for the per-blip behaviour.
///
/// The whole radar overlay is only shown while it is useful: at least one live target, first-person is active,
/// AND the match is in its Seek phase. It is hidden by switching the overlay camera's rendering off (not by
/// deactivating the GameObjects), so hidden blips keep counting down their lifetime and self-destruct on schedule.
///
[DisallowMultipleComponent]
public sealed class Radar : MonoBehaviour
{
/// The scene's single radar overlay (lives in the persistent Main scene). Hunter clients spawn
/// hider blips onto it from MatchManager's radar-ping sweep.
public static Radar Instance { get; private set; }
[Tooltip("Template each spawned Target is cloned from. Auto-resolves to the child \"Target Template\".")]
[SerializeField] private Transform targetTemplate;
[Tooltip("Camera the direction is measured FROM (camera -> target). Auto-resolves to the Camera this radar sits under.")]
[SerializeField] private Camera referenceCamera;
[Tooltip("Overlay camera that renders the radar. Its rendering is toggled off unless the radar should show " +
"(at least one live target AND first-person active). Auto-resolves to the Camera this radar sits under.")]
[SerializeField] private Camera radarCamera;
[Tooltip("First-person rig. The radar is only shown while first-person is active. Empty = found automatically.")]
[SerializeField] private FirstPersonController firstPerson;
// Live blips, pruned as they self-destruct; the radar shows only while at least one is alive.
private readonly List _blips = new List();
private void Awake()
{
Instance = this;
if (!targetTemplate)
{
var t = transform.Find("Target Template");
if (t) targetTemplate = t;
}
if (!referenceCamera) referenceCamera = GetComponentInParent();
if (!radarCamera) radarCamera = GetComponentInParent();
if (!firstPerson) firstPerson = FindFirstObjectByType(FindObjectsInactive.Include);
ApplyVisibility(false); // hidden until a target exists, first-person is live AND the match is seeking
}
private void OnDestroy()
{
if (Instance == this) Instance = null;
}
///
/// Spawns a Target blip that each frame orients toward (from the reference
/// camera) and destroys itself after seconds. Returns the spawned blip, or
/// null if it could not be created.
///
public RadarTarget Spawn(Transform target, float lifetime)
{
if (!target)
{
Debug.LogWarning("[Radar] Spawn called without a target transform.", this);
return null;
}
if (!targetTemplate)
{
Debug.LogWarning("[Radar] No Target Template assigned or found.", this);
return null;
}
Transform clone = Instantiate(targetTemplate, targetTemplate.parent);
clone.name = "Target";
clone.localPosition = targetTemplate.localPosition;
clone.localScale = targetTemplate.localScale;
clone.gameObject.SetActive(true);
var blip = clone.GetComponent();
blip.Init(target, referenceCamera, lifetime);
_blips.Add(blip);
return blip;
}
// LateUpdate so the count reflects any blip that self-destructed this frame, in step with RadarTarget's aim.
private void LateUpdate()
{
// Drop self-destructed blips (Destroy leaves a fake-null entry behind).
for (int i = _blips.Count - 1; i >= 0; i--)
if (!_blips[i]) _blips.RemoveAt(i);
bool visible = _blips.Count > 0 && firstPerson && firstPerson.enabled && InSeekPhase();
ApplyVisibility(visible);
}
// The radar only makes sense during the seek phase (hunters chasing hiders). Blips only spawn then anyway,
// but a blip's lifetime can outlast the phase edge, so gating here hides the overlay the instant Seek ends.
private static bool InSeekPhase()
{
var m = MatchManager.Instance;
return m && m.MatchActive && m.LocalSubPhase == MatchManager.MatchSubPhase.Seek;
}
// Shows/hides the whole radar overlay in one toggle (disc + blips) by switching the overlay camera's
// rendering. The GameObjects stay active, so blips keep ticking down their lifetime while hidden. The
// overlay renders only the Radar layer, so nothing else is affected.
private void ApplyVisibility(bool visible)
{
if (radarCamera && radarCamera.enabled != visible)
radarCamera.enabled = visible;
}
}