using UnityEngine; using TMPro; /// /// Place this component on a GameObject to create a checkpoint zone. /// When the player enters, it will save the current game state. /// [RequireComponent(typeof(BoxCollider))] public class CheckpointTrigger : MonoBehaviour { [Header("Checkpoint Settings")] [Tooltip("Show a visual effect when checkpoint is activated")] public bool showVisualFeedback = true; [Tooltip("Only trigger once, or every time player enters")] public bool oneTimeUse = false; [Tooltip("Custom checkpoint message")] public string checkpointMessage = "Checkpoint Saved"; [Header("Visual Feedback")] public GameObject checkpointVFX; public AudioClip checkpointSound; public TextMeshProUGUI checkpointText; public CanvasGroup textCanvasGroup; [Header("Fade Animation")] [Tooltip("Duration of fade in/out animation")] public float fadeDuration = 0.5f; [Tooltip("How long the message stays visible")] public float displayDuration = 2f; private bool hasBeenTriggered = false; private BoxCollider triggerCollider; private AudioSource audioSource; private void Awake() { // Ensure collider is trigger triggerCollider = GetComponent(); if (triggerCollider != null) { triggerCollider.isTrigger = true; } // Setup audio source if sound is assigned if (checkpointSound != null) { audioSource = gameObject.AddComponent(); audioSource.clip = checkpointSound; audioSource.playOnAwake = false; } } private void OnTriggerEnter(Collider other) { // Check if player entered if (other.CompareTag("Player")) { // If one-time use and already triggered, ignore if (oneTimeUse && hasBeenTriggered) return; ActivateCheckpoint(); } } /// /// Activate this checkpoint and save game state /// public void ActivateCheckpoint() { CheckpointSystem checkpointSystem = CheckpointSystem.Instance; if (checkpointSystem != null) { // Save checkpoint at this position checkpointSystem.SaveCheckpointAt(transform.position); Debug.Log($"[Checkpoint] {checkpointMessage} at {transform.position}"); // Show feedback if (showVisualFeedback) { ShowFeedback(); } hasBeenTriggered = true; } else { Debug.LogWarning("[Checkpoint] CheckpointSystem not found!"); } } private void ShowFeedback() { // Play sound if (audioSource != null && checkpointSound != null) { audioSource.Play(); } // Spawn VFX if (checkpointVFX != null) { checkpointVFX.SetActive(true); Destroy(checkpointVFX, fadeDuration * 2 + displayDuration); } // Show text with smooth fade animation if (checkpointText != null && textCanvasGroup != null) { checkpointText.text = checkpointMessage; checkpointText.gameObject.SetActive(true); StartCoroutine(FadeTextInOut()); } Debug.Log($"[Checkpoint] ✓ {checkpointMessage}"); } private System.Collections.IEnumerator FadeTextInOut() { // Fade in from 0 to 1 float elapsed = 0f; while (elapsed < fadeDuration) { elapsed += Time.deltaTime; textCanvasGroup.alpha = Mathf.Lerp(0f, 1f, elapsed / fadeDuration); yield return null; } textCanvasGroup.alpha = 1f; // Display at full opacity yield return new WaitForSeconds(displayDuration); // Fade out from 1 to 0 elapsed = 0f; while (elapsed < fadeDuration) { elapsed += Time.deltaTime; textCanvasGroup.alpha = Mathf.Lerp(1f, 0f, elapsed / fadeDuration); yield return null; } textCanvasGroup.alpha = 0f; // Deactivate text object checkpointText.gameObject.SetActive(false); } /// /// Reset this checkpoint so it can be triggered again /// public void ResetCheckpoint() { hasBeenTriggered = false; } // Visualize checkpoint in editor private void OnDrawGizmos() { Gizmos.color = hasBeenTriggered ? Color.green : Color.yellow; Gizmos.DrawWireCube(transform.position, Vector3.one * 2f); Gizmos.color = Color.cyan; Gizmos.DrawLine(transform.position, transform.position + Vector3.up * 3f); } }