Clean up IPausable interafaces a little bit and start refactoring the pause-game flow in the minigame
This commit is contained in:
@@ -1,304 +1,255 @@
|
||||
using UnityEngine;
|
||||
using AppleHills.Core.Settings;
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using AppleHills.Core.Interfaces;
|
||||
using Core;
|
||||
using UI;
|
||||
using AppleHills.Core.Settings;
|
||||
using Bootstrap;
|
||||
using UI;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// Singleton manager for global game state and settings. Provides accessors for various gameplay parameters.
|
||||
/// </summary>
|
||||
public class GameManager : MonoBehaviour
|
||||
namespace Core
|
||||
{
|
||||
private static GameManager _instance;
|
||||
private static bool _isQuitting = false;
|
||||
|
||||
/// <summary>
|
||||
/// Singleton instance of the GameManager. No longer creates an instance if one doesn't exist.
|
||||
/// Singleton manager for global game state and settings. Provides accessors for various gameplay parameters.
|
||||
/// </summary>
|
||||
public static GameManager Instance => _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;
|
||||
|
||||
/// <summary>
|
||||
/// Current pause state of the game
|
||||
/// </summary>
|
||||
public bool IsPaused => _isPaused;
|
||||
|
||||
// List of pausable components that have registered with the GameManager
|
||||
private List<IPausable> _pausableComponents = new List<IPausable>();
|
||||
|
||||
// Events for pause state changes
|
||||
public event Action OnGamePaused;
|
||||
public event Action OnGameResumed;
|
||||
|
||||
void Awake()
|
||||
public class GameManager : MonoBehaviour
|
||||
{
|
||||
_instance = this;
|
||||
// Singleton implementation
|
||||
private static GameManager _instance;
|
||||
public static GameManager Instance => _instance;
|
||||
private static bool _isQuitting = false;
|
||||
|
||||
// Create settings provider if it doesn't exist
|
||||
SettingsProvider.Instance.gameObject.name = "Settings Provider";
|
||||
private bool _settingsLoaded = false;
|
||||
private bool _developerSettingsLoaded = false;
|
||||
|
||||
// Create developer settings provider if it doesn't exist
|
||||
DeveloperSettingsProvider.Instance.gameObject.name = "Developer Settings Provider";
|
||||
|
||||
// Load all settings synchronously during Awake
|
||||
InitializeSettings();
|
||||
InitializeDeveloperSettings();
|
||||
|
||||
// Register for post-boot initialization
|
||||
BootCompletionService.RegisterInitAction(InitializePostBoot);
|
||||
|
||||
// DontDestroyOnLoad(gameObject);
|
||||
}
|
||||
// Pausable implementation
|
||||
private bool _isPaused = false;
|
||||
public bool IsPaused => _isPaused;
|
||||
|
||||
private void InitializePostBoot()
|
||||
{
|
||||
// Find and subscribe to PauseMenu events
|
||||
PauseMenu pauseMenu = PauseMenu.Instance;
|
||||
if (pauseMenu != null)
|
||||
// List of pausable components that have registered with the GameManager
|
||||
private List<IPausable> _pausableComponents = new List<IPausable>();
|
||||
|
||||
// Events for pause state changes
|
||||
public event Action OnGamePaused;
|
||||
public event Action OnGameResumed;
|
||||
|
||||
void Awake()
|
||||
{
|
||||
pauseMenu.OnGamePaused += OnPauseMenuPaused;
|
||||
pauseMenu.OnGameResumed += OnPauseMenuResumed;
|
||||
_instance = this;
|
||||
|
||||
// Create settings providers if it doesn't exist
|
||||
SettingsProvider.Instance.gameObject.name = "Settings Provider";
|
||||
DeveloperSettingsProvider.Instance.gameObject.name = "Developer Settings Provider";
|
||||
|
||||
// Load all settings synchronously during Awake
|
||||
InitializeSettings();
|
||||
InitializeDeveloperSettings();
|
||||
|
||||
// Register for post-boot initialization
|
||||
BootCompletionService.RegisterInitAction(InitializePostBoot);
|
||||
|
||||
// DontDestroyOnLoad(gameObject);
|
||||
}
|
||||
|
||||
private void InitializePostBoot()
|
||||
{
|
||||
// For post-boot correct initialization order
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Register a component as pausable, so it receives pause/resume notifications
|
||||
/// </summary>
|
||||
/// <param name="component">The pausable component to register</param>
|
||||
public void RegisterPausableComponent(IPausable component)
|
||||
{
|
||||
if (component != null && !_pausableComponents.Contains(component))
|
||||
{
|
||||
_pausableComponents.Add(component);
|
||||
|
||||
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<PauseMenu>();
|
||||
if (pauseMenu != null)
|
||||
{
|
||||
pauseMenu.OnGamePaused -= OnPauseMenuPaused;
|
||||
pauseMenu.OnGameResumed -= OnPauseMenuResumed;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Register a component as pausable, so it receives pause/resume notifications
|
||||
/// </summary>
|
||||
/// <param name="component">The pausable component to register</param>
|
||||
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();
|
||||
}
|
||||
|
||||
// If the game is already paused, pause the component immediately
|
||||
if (_isPaused)
|
||||
Logging.Debug($"[GameManager] Registered pausable component: {(component as MonoBehaviour)?.name ?? "Unknown"}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unregister a pausable component
|
||||
/// </summary>
|
||||
/// <param name="component">The pausable component to unregister</param>
|
||||
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"}");
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Revisit this with proper pause menu request implementation
|
||||
public void RequestGamePause()
|
||||
{
|
||||
PauseGame();
|
||||
}
|
||||
|
||||
public void RequestGameResume()
|
||||
{
|
||||
ResumeGame();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pause the game and notify all registered pausable components
|
||||
/// </summary>
|
||||
private 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.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resume the game and notify all registered pausable components
|
||||
/// </summary>
|
||||
private 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.");
|
||||
}
|
||||
|
||||
private void InitializeSettings()
|
||||
{
|
||||
Logging.Debug("Starting settings initialization...");
|
||||
|
||||
// Load settings synchronously
|
||||
var playerSettings = SettingsProvider.Instance.LoadSettingsSynchronous<PlayerFollowerSettings>();
|
||||
var interactionSettings = SettingsProvider.Instance.LoadSettingsSynchronous<InteractionSettings>();
|
||||
var minigameSettings = SettingsProvider.Instance.LoadSettingsSynchronous<DivingMinigameSettings>();
|
||||
|
||||
// Register settings with service locator
|
||||
if (playerSettings != null)
|
||||
{
|
||||
ServiceLocator.Register<IPlayerFollowerSettings>(playerSettings);
|
||||
Logging.Debug("PlayerFollowerSettings registered successfully");
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("Failed to load PlayerFollowerSettings");
|
||||
}
|
||||
|
||||
Logging.Debug($"[GameManager] Registered pausable component: {(component as MonoBehaviour)?.name ?? "Unknown"}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unregister a pausable component
|
||||
/// </summary>
|
||||
/// <param name="component">The pausable component to unregister</param>
|
||||
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"}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when the PauseMenu broadcasts a pause event
|
||||
/// </summary>
|
||||
private void OnPauseMenuPaused()
|
||||
{
|
||||
PauseGame();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when the PauseMenu broadcasts a resume event
|
||||
/// </summary>
|
||||
private void OnPauseMenuResumed()
|
||||
{
|
||||
ResumeGame();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pause the game and notify all registered pausable components
|
||||
/// </summary>
|
||||
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.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resume the game and notify all registered pausable components
|
||||
/// </summary>
|
||||
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.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Toggle the pause state of the game
|
||||
/// </summary>
|
||||
public void TogglePause()
|
||||
{
|
||||
if (_isPaused)
|
||||
ResumeGame();
|
||||
else
|
||||
PauseGame();
|
||||
}
|
||||
|
||||
private void InitializeSettings()
|
||||
{
|
||||
Logging.Debug("Starting settings initialization...");
|
||||
|
||||
// Load settings synchronously
|
||||
var playerSettings = SettingsProvider.Instance.LoadSettingsSynchronous<PlayerFollowerSettings>();
|
||||
var interactionSettings = SettingsProvider.Instance.LoadSettingsSynchronous<InteractionSettings>();
|
||||
var minigameSettings = SettingsProvider.Instance.LoadSettingsSynchronous<DivingMinigameSettings>();
|
||||
|
||||
// Register settings with service locator
|
||||
if (playerSettings != null)
|
||||
{
|
||||
ServiceLocator.Register<IPlayerFollowerSettings>(playerSettings);
|
||||
Logging.Debug("PlayerFollowerSettings registered successfully");
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("Failed to load PlayerFollowerSettings");
|
||||
}
|
||||
if (interactionSettings != null)
|
||||
{
|
||||
ServiceLocator.Register<IInteractionSettings>(interactionSettings);
|
||||
Logging.Debug("InteractionSettings registered successfully");
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("Failed to load InteractionSettings");
|
||||
}
|
||||
|
||||
if (interactionSettings != null)
|
||||
{
|
||||
ServiceLocator.Register<IInteractionSettings>(interactionSettings);
|
||||
Logging.Debug("InteractionSettings registered successfully");
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("Failed to load InteractionSettings");
|
||||
}
|
||||
|
||||
if (minigameSettings != null)
|
||||
{
|
||||
ServiceLocator.Register<IDivingMinigameSettings>(minigameSettings);
|
||||
Logging.Debug("MinigameSettings registered successfully");
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("Failed to load MinigameSettings");
|
||||
if (minigameSettings != null)
|
||||
{
|
||||
ServiceLocator.Register<IDivingMinigameSettings>(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");
|
||||
}
|
||||
}
|
||||
|
||||
// Log success
|
||||
_settingsLoaded = playerSettings != null && interactionSettings != null && minigameSettings != null;
|
||||
if (_settingsLoaded)
|
||||
/// <summary>
|
||||
/// Check for and initialize developer settings.
|
||||
/// </summary>
|
||||
private void InitializeDeveloperSettings()
|
||||
{
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check for and initialize developer settings.
|
||||
/// </summary>
|
||||
private void InitializeDeveloperSettings()
|
||||
{
|
||||
Logging.Debug("Starting developer settings initialization...");
|
||||
Logging.Debug("Starting developer settings initialization...");
|
||||
|
||||
// Load developer settings
|
||||
var divingDevSettings = DeveloperSettingsProvider.Instance.GetSettings<DivingDeveloperSettings>();
|
||||
// Load developer settings
|
||||
var divingDevSettings = DeveloperSettingsProvider.Instance.GetSettings<DivingDeveloperSettings>();
|
||||
|
||||
_developerSettingsLoaded = divingDevSettings != null;
|
||||
_developerSettingsLoaded = divingDevSettings != null;
|
||||
|
||||
if (_developerSettingsLoaded)
|
||||
{
|
||||
Logging.Debug("All developer settings loaded successfully");
|
||||
if (_developerSettingsLoaded)
|
||||
{
|
||||
Logging.Debug("All developer settings loaded successfully");
|
||||
}
|
||||
else
|
||||
{
|
||||
Logging.Warning("Some developer settings failed to load");
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
void OnApplicationQuit()
|
||||
{
|
||||
Logging.Warning("Some developer settings failed to load");
|
||||
_isQuitting = true;
|
||||
ServiceLocator.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
void OnApplicationQuit()
|
||||
{
|
||||
_isQuitting = true;
|
||||
ServiceLocator.Clear();
|
||||
}
|
||||
// Helper method to get settings
|
||||
private T GetSettings<T>() where T : class
|
||||
{
|
||||
return ServiceLocator.Get<T>();
|
||||
}
|
||||
|
||||
// Helper method to get settings
|
||||
private T GetSettings<T>() where T : class
|
||||
{
|
||||
return ServiceLocator.Get<T>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the entire settings object of specified type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type of settings to retrieve</typeparam>
|
||||
/// <returns>The settings object or null if not found</returns>
|
||||
public static T GetSettingsObject<T>() where T : class
|
||||
{
|
||||
return Instance?.GetSettings<T>();
|
||||
}
|
||||
/// <summary>
|
||||
/// Returns the entire settings object of specified type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type of settings to retrieve</typeparam>
|
||||
/// <returns>The settings object or null if not found</returns>
|
||||
public static T GetSettingsObject<T>() where T : class
|
||||
{
|
||||
return Instance?.GetSettings<T>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the developer settings object of specified type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type of developer settings to retrieve</typeparam>
|
||||
/// <returns>The developer settings object or null if not found</returns>
|
||||
public static T GetDeveloperSettings<T>() where T : BaseDeveloperSettings
|
||||
{
|
||||
return DeveloperSettingsProvider.Instance?.GetSettings<T>();
|
||||
}
|
||||
/// <summary>
|
||||
/// Returns the developer settings object of specified type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type of developer settings to retrieve</typeparam>
|
||||
/// <returns>The developer settings object or null if not found</returns>
|
||||
public static T GetDeveloperSettings<T>() where T : BaseDeveloperSettings
|
||||
{
|
||||
return DeveloperSettingsProvider.Instance?.GetSettings<T>();
|
||||
}
|
||||
|
||||
// LEFTOVER LEGACY SETTINGS
|
||||
public float PlayerStopDistance => GetSettings<IInteractionSettings>()?.PlayerStopDistance ?? 6.0f;
|
||||
public float PlayerStopDistanceDirectInteraction => GetSettings<IInteractionSettings>()?.PlayerStopDistanceDirectInteraction ?? 2.0f;
|
||||
public float DefaultPuzzlePromptRange => GetSettings<IInteractionSettings>()?.DefaultPuzzlePromptRange ?? 3.0f;
|
||||
// LEFTOVER LEGACY SETTINGS
|
||||
public float PlayerStopDistance => GetSettings<IInteractionSettings>()?.PlayerStopDistance ?? 6.0f;
|
||||
public float PlayerStopDistanceDirectInteraction => GetSettings<IInteractionSettings>()?.PlayerStopDistanceDirectInteraction ?? 2.0f;
|
||||
public float DefaultPuzzlePromptRange => GetSettings<IInteractionSettings>()?.DefaultPuzzlePromptRange ?? 3.0f;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,10 +16,5 @@ namespace AppleHills.Core.Interfaces
|
||||
/// Resumes the component's functionality
|
||||
/// </summary>
|
||||
void DoResume();
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether the component is currently paused
|
||||
/// </summary>
|
||||
bool IsPaused { get; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using UnityEngine;
|
||||
using Core;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AppleHills
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user