CheckpointTrigger.cs 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. using UnityEngine;
  2. using TMPro;
  3. /// <summary>
  4. /// Place this component on a GameObject to create a checkpoint zone.
  5. /// When the player enters, it will save the current game state.
  6. /// </summary>
  7. [RequireComponent(typeof(BoxCollider))]
  8. public class CheckpointTrigger : MonoBehaviour
  9. {
  10. [Header("Checkpoint Settings")]
  11. [Tooltip("Show a visual effect when checkpoint is activated")]
  12. public bool showVisualFeedback = true;
  13. [Tooltip("Only trigger once, or every time player enters")]
  14. public bool oneTimeUse = false;
  15. [Tooltip("Custom checkpoint message")]
  16. public string checkpointMessage = "Checkpoint Saved";
  17. [Header("Visual Feedback")]
  18. public GameObject checkpointVFX;
  19. public AudioClip checkpointSound;
  20. public TextMeshProUGUI checkpointText;
  21. public CanvasGroup textCanvasGroup;
  22. [Header("Fade Animation")]
  23. [Tooltip("Duration of fade in/out animation")]
  24. public float fadeDuration = 0.5f;
  25. [Tooltip("How long the message stays visible")]
  26. public float displayDuration = 2f;
  27. private bool hasBeenTriggered = false;
  28. private BoxCollider triggerCollider;
  29. private AudioSource audioSource;
  30. private void Awake()
  31. {
  32. // Ensure collider is trigger
  33. triggerCollider = GetComponent<BoxCollider>();
  34. if (triggerCollider != null)
  35. {
  36. triggerCollider.isTrigger = true;
  37. }
  38. // Setup audio source if sound is assigned
  39. if (checkpointSound != null)
  40. {
  41. audioSource = gameObject.AddComponent<AudioSource>();
  42. audioSource.clip = checkpointSound;
  43. audioSource.playOnAwake = false;
  44. }
  45. }
  46. private void OnTriggerEnter(Collider other)
  47. {
  48. // Check if player entered
  49. if (other.CompareTag("Player"))
  50. {
  51. // If one-time use and already triggered, ignore
  52. if (oneTimeUse && hasBeenTriggered)
  53. return;
  54. ActivateCheckpoint();
  55. }
  56. }
  57. /// <summary>
  58. /// Activate this checkpoint and save game state
  59. /// </summary>
  60. public void ActivateCheckpoint()
  61. {
  62. CheckpointSystem checkpointSystem = CheckpointSystem.Instance;
  63. if (checkpointSystem != null)
  64. {
  65. // Save checkpoint at this position
  66. checkpointSystem.SaveCheckpointAt(transform.position);
  67. Debug.Log($"[Checkpoint] {checkpointMessage} at {transform.position}");
  68. // Show feedback
  69. if (showVisualFeedback)
  70. {
  71. ShowFeedback();
  72. }
  73. hasBeenTriggered = true;
  74. }
  75. else
  76. {
  77. Debug.LogWarning("[Checkpoint] CheckpointSystem not found!");
  78. }
  79. }
  80. private void ShowFeedback()
  81. {
  82. // Play sound
  83. if (audioSource != null && checkpointSound != null)
  84. {
  85. audioSource.Play();
  86. }
  87. // Spawn VFX
  88. if (checkpointVFX != null)
  89. {
  90. checkpointVFX.SetActive(true);
  91. Destroy(checkpointVFX, fadeDuration * 2 + displayDuration);
  92. }
  93. // Show text with smooth fade animation
  94. if (checkpointText != null && textCanvasGroup != null)
  95. {
  96. checkpointText.text = checkpointMessage;
  97. checkpointText.gameObject.SetActive(true);
  98. StartCoroutine(FadeTextInOut());
  99. }
  100. Debug.Log($"[Checkpoint] ✓ {checkpointMessage}");
  101. }
  102. private System.Collections.IEnumerator FadeTextInOut()
  103. {
  104. // Fade in from 0 to 1
  105. float elapsed = 0f;
  106. while (elapsed < fadeDuration)
  107. {
  108. elapsed += Time.deltaTime;
  109. textCanvasGroup.alpha = Mathf.Lerp(0f, 1f, elapsed / fadeDuration);
  110. yield return null;
  111. }
  112. textCanvasGroup.alpha = 1f;
  113. // Display at full opacity
  114. yield return new WaitForSeconds(displayDuration);
  115. // Fade out from 1 to 0
  116. elapsed = 0f;
  117. while (elapsed < fadeDuration)
  118. {
  119. elapsed += Time.deltaTime;
  120. textCanvasGroup.alpha = Mathf.Lerp(1f, 0f, elapsed / fadeDuration);
  121. yield return null;
  122. }
  123. textCanvasGroup.alpha = 0f;
  124. // Deactivate text object
  125. checkpointText.gameObject.SetActive(false);
  126. }
  127. /// <summary>
  128. /// Reset this checkpoint so it can be triggered again
  129. /// </summary>
  130. public void ResetCheckpoint()
  131. {
  132. hasBeenTriggered = false;
  133. }
  134. // Visualize checkpoint in editor
  135. private void OnDrawGizmos()
  136. {
  137. Gizmos.color = hasBeenTriggered ? Color.green : Color.yellow;
  138. Gizmos.DrawWireCube(transform.position, Vector3.one * 2f);
  139. Gizmos.color = Color.cyan;
  140. Gizmos.DrawLine(transform.position, transform.position + Vector3.up * 3f);
  141. }
  142. }