SpaceQuestions_MarioKart/Assets/Scripts/GateCenterDetector.cs
2025-12-11 13:14:43 +01:00

120 lines
3.5 KiB
C#

// GateCenterDetector.cs
// Zweck: Prüft jedes Frame, welches Gate am nächsten zur Bildmitte liegt, und zeigt dessen Text im HUD.
using UnityEngine;
public class GateCenterDetector : MonoBehaviour
{
[Header("XR Camera")]
[SerializeField] private Camera xrCamera;
[Header("References")]
[SerializeField] private GateSpawner gateSpawner;
[SerializeField] private CockpitGateHUD cockpitHUD;
[Header("Selection")]
[Tooltip("Max. Weltdistanz (0 = ignorieren).")]
[SerializeField] private float maxWorldDistance = 0f;
[Tooltip("Max. quadratische Distanz zur Bildschirmmitte im Viewport (0..1).")]
[SerializeField] private float maxCenterDistSqr = 0.05f;
[Header("Debug")]
[SerializeField] private bool debugLogs = false;
private GateText currentGate;
private void Awake()
{
if (!xrCamera)
{
xrCamera = GetComponent<Camera>();
if (!xrCamera && Camera.main != null)
xrCamera = Camera.main;
}
if (debugLogs)
{
if (!xrCamera) Debug.LogWarning("[GateCenterDetector] XR Camera fehlt.");
if (!gateSpawner) Debug.LogWarning("[GateCenterDetector] GateSpawner fehlt.");
if (!cockpitHUD) Debug.LogWarning("[GateCenterDetector] CockpitGateHUD fehlt.");
}
}
private void Update()
{
if (!xrCamera || !gateSpawner || !cockpitHUD)
return;
var gates = gateSpawner.ActiveGates;
if (gates == null || gates.Count == 0)
{
ClearCurrentGate();
return;
}
GateText bestGate = null;
float bestScore = float.MaxValue;
Vector3 camPos = xrCamera.transform.position;
foreach (var gateObj in gates)
{
if (!gateObj) continue;
var gateQuestion = gateObj.GetComponentInChildren<GateText>();
if (!gateQuestion) continue;
Vector3 worldPos = gateObj.transform.position;
// optional: Distanzlimit
if (maxWorldDistance > 0f)
{
float dist = Vector3.Distance(camPos, worldPos);
if (dist > maxWorldDistance) continue;
}
// in Viewport projizieren
Vector3 v = xrCamera.WorldToViewportPoint(worldPos);
if (v.z <= 0f) continue; // hinter Kamera
if (v.x < 0f || v.x > 1f || v.y < 0f || v.y > 1f) continue; // off-screen
// Distanz zur Mitte (0.5/0.5)
float dx = v.x - 0.5f;
float dy = v.y - 0.5f;
float distSqr = dx * dx + dy * dy;
if (distSqr < bestScore)
{
bestScore = distSqr;
bestGate = gateQuestion;
}
}
if (bestGate != null && (maxCenterDistSqr <= 0f || bestScore <= maxCenterDistSqr))
{
if (bestGate != currentGate)
{
currentGate = bestGate;
string text = currentGate.GetQuestionText();
cockpitHUD.ShowWithReveal(text);
if (debugLogs)
Debug.Log($"[GateCenterDetector] Fokus: {currentGate.name} | Text: {text}");
}
}
else
{
ClearCurrentGate();
}
}
private void ClearCurrentGate()
{
if (currentGate != null)
{
if (debugLogs) Debug.Log("[GateCenterDetector] Fokus verloren, HUD aus.");
currentGate = null;
cockpitHUD.Hide();
}
}
}