Danro/Assets/Scripts/Behaviour/Checkpoints/CheckpointSystem.cs

121 lines
4.1 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 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<Checkpoint, Checkpoint> ActiveChanged;
// Дополнительные события с современным синтаксисом
public event Action<Checkpoint> OnCheckpointActivated;
public event Action<Checkpoint> OnCheckpointDeactivated;
// Текущий активный чекпоинт (read-only)
public Checkpoint Active => _active;
private 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(); // гарантируем запись на диск
}
// Оповестим подписчиков о смене
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<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;
}
}
}