Danro/Assets/Resources/Scripts/GameManager.cs

203 lines
5.4 KiB
C#

using System;
using System.IO;
using UnityEngine;
using UnityEngine.SceneManagement;
[DefaultExecutionOrder(-1000)]
public class GameManager : MonoBehaviour
{
public static GameManager Instance { get; private set; }
public bool IsPaused { get; private set; }
public event Action<bool> PauseStateChanged;
public int world { get; private set; } = 1;
public int stage { get; private set; } = 1;
public int stagesByWorld { get; private set; } = 5;
public int lives { get; private set; } = 3;
public int coins { get; private set; } = 0;
public GameObject playerObj { get; private set; }
[SerializeField] private GameObject playerPrefab;
[SerializeField] private string playerPrefabResourcePath = "Prefabs/Player";
private bool _shouldSpawnPlayer;
private void OnEnable() => SceneManager.sceneLoaded += OnSceneLoaded;
private void OnDisable() => SceneManager.sceneLoaded -= OnSceneLoaded;
public event Action<GameObject> PlayerSpawned;
public event Action<int> CoinsChanged;
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
private static void Bootstrap()
{
if (Instance == null)
{
var go = new GameObject(nameof(GameManager));
Instance = go.AddComponent<GameManager>();
DontDestroyOnLoad(go);
}
}
private void Awake()
{
if (Instance != null && Instance != this)
{
Destroy(gameObject);
return;
}
Instance = this;
DontDestroyOnLoad(gameObject);
}
private void OnDestroy()
{
if (Instance == this) Instance = null;
}
//private void Start()
//{
// //Application.targetFrameRate = 60;
// //LoadScene("MainMenu", false);
// //NewGame();
// if (SceneManager.GetActiveScene().name != "MainMenu")
// {
// TrySpawnPlayerForActiveScene();
// }
//}
private GameObject ResolvePlayerPrefab()
{
if (playerPrefab != null) return playerPrefab;
var loaded = Resources.Load<GameObject>(playerPrefabResourcePath);
if (loaded == null)
{
Debug.LogError(
$"GameManager: playerPrefab is null. Resources.Load('{playerPrefabResourcePath}') вернул null. " +
$"Ожидается файл: Assets/Resources/{playerPrefabResourcePath}.prefab (точное совпадение регистра).");
}
return loaded;
}
public void NewGame()
{
lives = 3;
coins = 0;
CoinsChanged?.Invoke(coins);
LoadLevel(1, 1);
}
public void GameOver() => LoadScene("MainMenu", false);
public void LoadLevel(int world, int stage)
{
this.world = world;
this.stage = stage;
string sceneName = $"{world}-{stage}";
if (SceneInBuildSettingsExists(sceneName))
{
LoadScene(sceneName);
}
else
{
print("WIN");
//NewGame();
LoadScene("MainMenu", false);
}
}
public void LoadScene(string sceneName, bool useUI = true)
{
_shouldSpawnPlayer = true;
SceneManager.LoadScene(sceneName);
if (useUI)
{
SceneManager.LoadScene("Level UI", LoadSceneMode.Additive);
}
else _shouldSpawnPlayer = false;
}
private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
{
TrySpawnPlayerForActiveScene();
}
private void TrySpawnPlayerForActiveScene()
{
if (!_shouldSpawnPlayer) return;
var spawn = FindFirstObjectByType<PlayerSpawn>();
Vector3 pos = spawn ? spawn.transform.position : new Vector3(0, 1.3f, 0);
Quaternion rot = spawn ? spawn.transform.rotation : Quaternion.identity;
playerObj = GameObject.FindGameObjectWithTag("Player");
if (playerObj != null) Destroy(playerObj);
var prefab = ResolvePlayerPrefab();
if (prefab == null) return;
playerObj = Instantiate(prefab, pos, rot);
SceneManager.MoveGameObjectToScene(playerObj, SceneManager.GetActiveScene());
PlayerSpawned?.Invoke(playerObj);
}
public void NextLevel()
{
if (stage >= stagesByWorld) LoadLevel(world + 1, 1);
else LoadLevel(world, stage + 1);
}
public void ResetLevel()
{
lives--;
//print($"Lives: {lives}");
if (lives > 0) LoadLevel(world, stage);
else GameOver();
}
public void AddCoin()
{
coins++;
if (coins >= 100)
{
coins = 0;
AddLife();
}
CoinsChanged?.Invoke(coins);
}
public void SetPause(bool pause)
{
if (IsPaused == pause) return;
IsPaused = pause;
Time.timeScale = pause ? 0f : 1f;
AudioListener.pause = pause;
PauseStateChanged?.Invoke(IsPaused);
}
public void TogglePause() => SetPause(!IsPaused);
public void AddLife() => lives++;
private static bool SceneInBuildSettingsExists(string sceneName)
{
int count = SceneManager.sceneCountInBuildSettings;
for (int i = 0; i < count; i++)
{
string path = SceneUtility.GetScenePathByBuildIndex(i);
if (Path.GetFileNameWithoutExtension(path) == sceneName)
return true;
}
return false;
}
}