using System; using UnityEngine; using UnityEngine.SceneManagement; namespace RR.Game2D.Entities { public class CheckpointSystem : MonoBehaviour { public static CheckpointSystem Instance { get; private set; } [Tooltip("Сохранять последний чекпоинт в PlayerPrefs (по имени сцены).")] public bool persistBetweenSessions = false; private Checkpoint _active; private Checkpoint[] _all; // Событие для внешних подписчиков: (старый, новый) public event Action ActiveChanged; // Дополнительные события с современным синтаксисом public event Action OnCheckpointActivated; public event Action OnCheckpointDeactivated; // Текущий активный чекпоинт (read-only) public Checkpoint Active => _active; private string PrefKey => $"CP_{SceneManager.GetActiveScene().name}"; private void Awake() { if (Instance && Instance != this) { Destroy(gameObject); return; } Instance = this; _all = FindObjectsByType(FindObjectsSortMode.None); // восстановление из PlayerPrefs if (persistBetweenSessions && PlayerPrefs.HasKey(PrefKey)) { var savedId = PlayerPrefs.GetString(PrefKey, ""); foreach (var cp in _all) if (cp.checkpointId == savedId) { _active = cp; break; } } } public void SetActive(Checkpoint cp) { if (_active == cp) return; // уже активен var previous = _active; _active = cp; if (persistBetweenSessions) { if (cp != null) PlayerPrefs.SetString(PrefKey, cp.checkpointId); else PlayerPrefs.DeleteKey(PrefKey); PlayerPrefs.Save(); // гарантируем запись на диск } // Оповестим подписчиков о смене ActiveChanged?.Invoke(previous, _active); // Оповещаем о деактивации предыдущего if (previous != null) OnCheckpointDeactivated?.Invoke(previous); // Оповещаем об активации нового if (_active != null) OnCheckpointActivated?.Invoke(_active); } // Новый вспомогательный метод: активировать чекпоинт по его идентификатору public void SetActiveById(string id) { if (string.IsNullOrWhiteSpace(id)) return; // Обновим кэш, если он по какой-то причине пуст if (_all == null || _all.Length == 0) _all = FindObjectsByType(FindObjectsSortMode.None); for (int i = 0; i < _all.Length; i++) { var cp = _all[i]; if (cp != null && cp.checkpointId == id) { SetActive(cp); return; } } // Если не нашли — ничего не делаем (можно добавить Debug.LogWarning при необходимости) } public Vector3 GetSpawnPosition(Vector3 defaultPos) => _active ? _active.GetSpawnPosition() : defaultPos; public Vector2 GetSpawnForward(Vector2 defaultForward) => _active ? _active.GetForward() : defaultForward; // Если нужно сбросить прогресс public void ClearSaved() { if (persistBetweenSessions) { PlayerPrefs.DeleteKey(PrefKey); PlayerPrefs.Save(); } _active = null; } } }