using UnityEngine; [DefaultExecutionOrder(-50)] public class RingCourseTracker : MonoBehaviour { [Tooltip("Drag each Ring object here in the order they must be flown through.")] [SerializeField] private Transform[] ringsInOrder; [SerializeField] private string landInstructionMessage = "All rings complete! Land the plane at the runway."; private RingCheckpoint[] checkpoints; private int nextRingIndex; private int ringsPassed; private bool courseComplete; public int RingsPassed => ringsPassed; public int TotalRings => checkpoints != null ? checkpoints.Length : 0; public bool CourseComplete => courseComplete; private void Awake() { BindRings(); } private void BindRings() { if (ringsInOrder == null || ringsInOrder.Length == 0) { Debug.LogWarning($"[RingCourse] No rings assigned on {name}.", this); checkpoints = System.Array.Empty(); return; } checkpoints = new RingCheckpoint[ringsInOrder.Length]; for (int i = 0; i < ringsInOrder.Length; i++) { Transform ringTransform = ringsInOrder[i]; if (ringTransform == null) { Debug.LogWarning($"[RingCourse] Ring slot {i + 1} is empty on {name}.", this); continue; } if (!ringTransform.TryGetComponent(out RingCheckpoint checkpoint)) checkpoint = ringTransform.gameObject.AddComponent(); checkpoint.Configure(this, i); checkpoint.ResetCheckpoint(); checkpoints[i] = checkpoint; } nextRingIndex = 0; ringsPassed = 0; courseComplete = false; if (TotalRings > 0 && checkpoints[0] != null) Debug.Log($"[RingCourse] Course started. Fly through ring 1: {checkpoints[0].name}"); } public void RegisterRingPass(RingCheckpoint ring) { if (courseComplete || ring == null || checkpoints == null) return; int ringIndex = System.Array.IndexOf(checkpoints, ring); if (ringIndex < 0) return; if (ring.Passed) return; if (ringIndex != nextRingIndex) { RingCheckpoint expected = checkpoints[nextRingIndex]; string expectedName = expected != null ? expected.name : $"ring {nextRingIndex + 1}"; Debug.LogWarning( $"[RingCourse] Wrong order. Pass {expectedName} next ({nextRingIndex + 1}/{TotalRings})."); return; } ring.MarkPassed(); ringsPassed++; nextRingIndex++; Debug.Log($"[RingCourse] Ring {ringsPassed}/{TotalRings} passed: {ring.name}"); if (ringsPassed >= TotalRings) { courseComplete = true; Debug.Log($"[RingCourse] {landInstructionMessage}"); return; } RingCheckpoint nextRing = checkpoints[nextRingIndex]; if (nextRing != null) Debug.Log($"[RingCourse] Next ring ({nextRingIndex + 1}/{TotalRings}): {nextRing.name}"); } #if UNITY_EDITOR [ContextMenu("Fill Rings From Children (scene order)")] private void FillRingsFromChildren() { ringsInOrder = new Transform[transform.childCount]; for (int i = 0; i < transform.childCount; i++) ringsInOrder[i] = transform.GetChild(i); UnityEditor.EditorUtility.SetDirty(this); } #endif }