Danro/Assets/Scripts/Behaviour/CheckpointSystem.cs

113 lines
3.9 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using UnityEngine;
using UnityEngine.SceneManagement;
namespace RR.Game2D.Entities
{
// Явный делегат для события смены чекпоинта
public delegate void CheckpointChangedHandler(Checkpoint previous, Checkpoint current);
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 CheckpointChangedHandler ActiveChanged;
// Текущий активный чекпоинт (read-only)
public Checkpoint Active => _active;
string PrefKey => $"CP_{SceneManager.GetActiveScene().name}";
void Awake()
{
if (Instance && Instance != this)
{
Destroy(gameObject);
return;
}
Instance = this;
_all = FindObjectsByType<Checkpoint>(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(); // гарантируем запись на диск
}
// Оповестим подписчиков о смене
if (ActiveChanged != null)
ActiveChanged(previous, _active);
// здесь можно задизейблить «подсветку» у старого и включить у нового
}
// Новый вспомогательный метод: активировать чекпоинт по его идентификатору
public void SetActiveById(string id)
{
if (string.IsNullOrWhiteSpace(id)) return;
// Обновим кэш, если он по какой-то причине пуст
if (_all == null || _all.Length == 0)
_all = FindObjectsByType<Checkpoint>(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;
}
}
}