// 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(); 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(); 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(); } } }