using UnityEngine;
using AppleHills.Core.Settings;
using System;
using System.Collections.Generic;
using AppleHills.Core.Interfaces;
using Core;
using UI;
///
/// Singleton manager for global game state and settings. Provides accessors for various gameplay parameters.
///
public class GameManager : MonoBehaviour
{
private static GameManager _instance;
private static bool _isQuitting = false;
///
/// Singleton instance of the GameManager.
///
public static GameManager Instance
{
get
{
if (_instance == null && Application.isPlaying && !_isQuitting)
{
_instance = FindAnyObjectByType();
if (_instance == null)
{
var go = new GameObject("GameManager");
_instance = go.AddComponent();
// DontDestroyOnLoad(go);
}
}
return _instance;
}
}
[Header("Settings Status")]
[SerializeField] private bool _settingsLoaded = false;
[SerializeField] private bool _developerSettingsLoaded = false;
public bool SettingsLoaded => _settingsLoaded;
public bool DeveloperSettingsLoaded => _developerSettingsLoaded;
[Header("Game State")]
[SerializeField] private bool _isPaused = false;
///
/// Current pause state of the game
///
public bool IsPaused => _isPaused;
// List of pausable components that have registered with the GameManager
private List _pausableComponents = new List();
// Events for pause state changes
public event Action OnGamePaused;
public event Action OnGameResumed;
void Awake()
{
_instance = this;
// Create settings provider if it doesn't exist
SettingsProvider.Instance.gameObject.name = "Settings Provider";
// Create developer settings provider if it doesn't exist
DeveloperSettingsProvider.Instance.gameObject.name = "Developer Settings Provider";
// Load all settings synchronously during Awake
InitializeSettings();
InitializeDeveloperSettings();
// DontDestroyOnLoad(gameObject);
}
private void Start()
{
// Find and subscribe to PauseMenu events
PauseMenu pauseMenu = PauseMenu.Instance;
if (pauseMenu != null)
{
pauseMenu.OnGamePaused += OnPauseMenuPaused;
pauseMenu.OnGameResumed += OnPauseMenuResumed;
Logging.Debug("[GameManager] Subscribed to PauseMenu events");
}
else
{
Logging.Warning("[GameManager] PauseMenu not found. Pause functionality won't work properly.");
}
}
private void OnDestroy()
{
// Unsubscribe from PauseMenu events
PauseMenu pauseMenu = FindFirstObjectByType();
if (pauseMenu != null)
{
pauseMenu.OnGamePaused -= OnPauseMenuPaused;
pauseMenu.OnGameResumed -= OnPauseMenuResumed;
}
}
///
/// Register a component as pausable, so it receives pause/resume notifications
///
/// The pausable component to register
public void RegisterPausableComponent(IPausable component)
{
if (component != null && !_pausableComponents.Contains(component))
{
_pausableComponents.Add(component);
// If the game is already paused, pause the component immediately
if (_isPaused)
{
component.Pause();
}
Logging.Debug($"[GameManager] Registered pausable component: {(component as MonoBehaviour)?.name ?? "Unknown"}");
}
}
///
/// Unregister a pausable component
///
/// The pausable component to unregister
public void UnregisterPausableComponent(IPausable component)
{
if (component != null && _pausableComponents.Contains(component))
{
_pausableComponents.Remove(component);
Logging.Debug($"[GameManager] Unregistered pausable component: {(component as MonoBehaviour)?.name ?? "Unknown"}");
}
}
///
/// Called when the PauseMenu broadcasts a pause event
///
private void OnPauseMenuPaused()
{
PauseGame();
}
///
/// Called when the PauseMenu broadcasts a resume event
///
private void OnPauseMenuResumed()
{
ResumeGame();
}
///
/// Pause the game and notify all registered pausable components
///
public void PauseGame()
{
if (_isPaused) return; // Already paused
_isPaused = true;
// Pause all registered components
foreach (var component in _pausableComponents)
{
component.Pause();
}
// Broadcast pause event
OnGamePaused?.Invoke();
Logging.Debug($"[GameManager] Game paused. Paused {_pausableComponents.Count} components.");
}
///
/// Resume the game and notify all registered pausable components
///
public void ResumeGame()
{
if (!_isPaused) return; // Already running
_isPaused = false;
// Resume all registered components
foreach (var component in _pausableComponents)
{
component.DoResume();
}
// Broadcast resume event
OnGameResumed?.Invoke();
Logging.Debug($"[GameManager] Game resumed. Resumed {_pausableComponents.Count} components.");
}
///
/// Toggle the pause state of the game
///
public void TogglePause()
{
if (_isPaused)
ResumeGame();
else
PauseGame();
}
private void InitializeSettings()
{
Logging.Debug("Starting settings initialization...");
// Load settings synchronously
var playerSettings = SettingsProvider.Instance.LoadSettingsSynchronous();
var interactionSettings = SettingsProvider.Instance.LoadSettingsSynchronous();
var minigameSettings = SettingsProvider.Instance.LoadSettingsSynchronous();
// Register settings with service locator
if (playerSettings != null)
{
ServiceLocator.Register(playerSettings);
Logging.Debug("PlayerFollowerSettings registered successfully");
}
else
{
Debug.LogError("Failed to load PlayerFollowerSettings");
}
if (interactionSettings != null)
{
ServiceLocator.Register(interactionSettings);
Logging.Debug("InteractionSettings registered successfully");
}
else
{
Debug.LogError("Failed to load InteractionSettings");
}
if (minigameSettings != null)
{
ServiceLocator.Register(minigameSettings);
Logging.Debug("MinigameSettings registered successfully");
}
else
{
Debug.LogError("Failed to load MinigameSettings");
}
// Log success
_settingsLoaded = playerSettings != null && interactionSettings != null && minigameSettings != null;
if (_settingsLoaded)
{
Logging.Debug("All settings loaded and registered with ServiceLocator");
}
else
{
Logging.Warning("Some settings failed to load - check that all settings assets exist and are marked as Addressables");
}
}
///
/// Check for and initialize developer settings.
///
private void InitializeDeveloperSettings()
{
Logging.Debug("Starting developer settings initialization...");
// Load developer settings
var divingDevSettings = DeveloperSettingsProvider.Instance.GetSettings();
_developerSettingsLoaded = divingDevSettings != null;
if (_developerSettingsLoaded)
{
Logging.Debug("All developer settings loaded successfully");
}
else
{
Logging.Warning("Some developer settings failed to load");
}
}
void OnApplicationQuit()
{
_isQuitting = true;
ServiceLocator.Clear();
}
// Helper method to get settings
private T GetSettings() where T : class
{
return ServiceLocator.Get();
}
///
/// Returns the entire settings object of specified type.
///
/// Type of settings to retrieve
/// The settings object or null if not found
public static T GetSettingsObject() where T : class
{
return Instance?.GetSettings();
}
///
/// Returns the developer settings object of specified type.
///
/// Type of developer settings to retrieve
/// The developer settings object or null if not found
public static T GetDeveloperSettings() where T : BaseDeveloperSettings
{
return DeveloperSettingsProvider.Instance?.GetSettings();
}
// LEFTOVER LEGACY SETTINGS
public float PlayerStopDistance => GetSettings()?.PlayerStopDistance ?? 6.0f;
public float PlayerStopDistanceDirectInteraction => GetSettings()?.PlayerStopDistanceDirectInteraction ?? 2.0f;
public float DefaultPuzzlePromptRange => GetSettings()?.DefaultPuzzlePromptRange ?? 3.0f;
}