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