Clean up IPausable interafaces a little bit and start refactoring the pause-game flow in the minigame

This commit is contained in:
Michal Adam Pikulski
2025-10-23 09:31:09 +02:00
parent 35acaddca5
commit ef3b4bf369
15 changed files with 423 additions and 579 deletions

View File

@@ -1,304 +1,255 @@
using UnityEngine; using System;
using AppleHills.Core.Settings;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using AppleHills.Core.Interfaces; using AppleHills.Core.Interfaces;
using Core; using AppleHills.Core.Settings;
using UI;
using Bootstrap; using Bootstrap;
using UI;
using UnityEngine;
/// <summary> namespace Core
/// Singleton manager for global game state and settings. Provides accessors for various gameplay parameters.
/// </summary>
public class GameManager : MonoBehaviour
{ {
private static GameManager _instance;
private static bool _isQuitting = false;
/// <summary> /// <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> /// </summary>
public static GameManager Instance => _instance; public class GameManager : MonoBehaviour
[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()
{ {
_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 private bool _settingsLoaded = false;
SettingsProvider.Instance.gameObject.name = "Settings Provider"; private bool _developerSettingsLoaded = false;
// Create developer settings provider if it doesn't exist // Pausable implementation
DeveloperSettingsProvider.Instance.gameObject.name = "Developer Settings Provider"; private bool _isPaused = false;
public bool IsPaused => _isPaused;
// Load all settings synchronously during Awake // List of pausable components that have registered with the GameManager
InitializeSettings(); private List<IPausable> _pausableComponents = new List<IPausable>();
InitializeDeveloperSettings();
// Register for post-boot initialization // Events for pause state changes
BootCompletionService.RegisterInitAction(InitializePostBoot); public event Action OnGamePaused;
public event Action OnGameResumed;
// DontDestroyOnLoad(gameObject); void Awake()
}
private void InitializePostBoot()
{
// Find and subscribe to PauseMenu events
PauseMenu pauseMenu = PauseMenu.Instance;
if (pauseMenu != null)
{ {
pauseMenu.OnGamePaused += OnPauseMenuPaused; _instance = this;
pauseMenu.OnGameResumed += OnPauseMenuResumed;
Logging.Debug("[GameManager] Subscribed to PauseMenu events"); // 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);
} }
else
private void InitializePostBoot()
{ {
Logging.Warning("[GameManager] PauseMenu not found. Pause functionality won't work properly."); // For post-boot correct initialization order
} }
}
private void OnDestroy() /// <summary>
{ /// Register a component as pausable, so it receives pause/resume notifications
// Unsubscribe from PauseMenu events /// </summary>
PauseMenu pauseMenu = FindFirstObjectByType<PauseMenu>(); /// <param name="component">The pausable component to register</param>
if (pauseMenu != null) public void RegisterPausableComponent(IPausable component)
{ {
pauseMenu.OnGamePaused -= OnPauseMenuPaused; if (component != null && !_pausableComponents.Contains(component))
pauseMenu.OnGameResumed -= OnPauseMenuResumed; {
_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"}");
}
} }
}
/// <summary> /// <summary>
/// Register a component as pausable, so it receives pause/resume notifications /// Unregister a pausable component
/// </summary> /// </summary>
/// <param name="component">The pausable component to register</param> /// <param name="component">The pausable component to unregister</param>
public void RegisterPausableComponent(IPausable component) public void UnregisterPausableComponent(IPausable component)
{
if (component != null && !_pausableComponents.Contains(component))
{ {
_pausableComponents.Add(component); if (component != null && _pausableComponents.Contains(component))
{
_pausableComponents.Remove(component);
Logging.Debug($"[GameManager] Unregistered pausable component: {(component as MonoBehaviour)?.name ?? "Unknown"}");
}
}
// If the game is already paused, pause the component immediately // TODO: Revisit this with proper pause menu request implementation
if (_isPaused) 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(); component.Pause();
} }
Logging.Debug($"[GameManager] Registered pausable component: {(component as MonoBehaviour)?.name ?? "Unknown"}"); // Broadcast pause event
} OnGamePaused?.Invoke();
}
/// <summary> Logging.Debug($"[GameManager] Game paused. Paused {_pausableComponents.Count} components.");
/// Unregister a pausable component }
/// </summary>
/// <param name="component">The pausable component to unregister</param> /// <summary>
public void UnregisterPausableComponent(IPausable component) /// Resume the game and notify all registered pausable components
{ /// </summary>
if (component != null && _pausableComponents.Contains(component)) private void ResumeGame()
{ {
_pausableComponents.Remove(component); if (!_isPaused) return; // Already running
Logging.Debug($"[GameManager] Unregistered pausable component: {(component as MonoBehaviour)?.name ?? "Unknown"}");
_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> private void InitializeSettings()
/// 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(); 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 (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");
}
} }
// Broadcast pause event /// <summary>
OnGamePaused?.Invoke(); /// Check for and initialize developer settings.
/// </summary>
private void InitializeDeveloperSettings()
{
Logging.Debug("Starting developer settings initialization...");
Logging.Debug($"[GameManager] Game paused. Paused {_pausableComponents.Count} components."); // Load developer settings
var divingDevSettings = DeveloperSettingsProvider.Instance.GetSettings<DivingDeveloperSettings>();
_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<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 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;
} }
/// <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 (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");
}
}
/// <summary>
/// Check for and initialize developer settings.
/// </summary>
private void InitializeDeveloperSettings()
{
Logging.Debug("Starting developer settings initialization...");
// Load developer settings
var divingDevSettings = DeveloperSettingsProvider.Instance.GetSettings<DivingDeveloperSettings>();
_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<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 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;
} }

View File

@@ -16,10 +16,5 @@ namespace AppleHills.Core.Interfaces
/// Resumes the component's functionality /// Resumes the component's functionality
/// </summary> /// </summary>
void DoResume(); void DoResume();
/// <summary>
/// Gets whether the component is currently paused
/// </summary>
bool IsPaused { get; }
} }
} }

View File

@@ -1,4 +1,5 @@
using UnityEngine; using Core;
using UnityEngine;
namespace AppleHills namespace AppleHills
{ {

View File

@@ -29,12 +29,6 @@ namespace Minigames.DivingForPictures
private Coroutine _wobbleCoroutine; private Coroutine _wobbleCoroutine;
private Coroutine _offScreenCheckCoroutine; private Coroutine _offScreenCheckCoroutine;
// Pause state tracking
private bool _isPaused = false;
// IPausable implementation
public bool IsPaused => _isPaused;
void Awake() void Awake()
{ {
// Cache references and randomize time offset for wobble // Cache references and randomize time offset for wobble
@@ -67,9 +61,8 @@ namespace Minigames.DivingForPictures
/// </summary> /// </summary>
public void Pause() public void Pause()
{ {
if (_isPaused) return; // Already paused if (GameManager.Instance.IsPaused) return; // Already paused
_isPaused = true;
StopBubbleBehavior(); StopBubbleBehavior();
// Debug log for troubleshooting // Debug log for troubleshooting
@@ -81,9 +74,8 @@ namespace Minigames.DivingForPictures
/// </summary> /// </summary>
public void DoResume() public void DoResume()
{ {
if (!_isPaused) return; // Already running if (!GameManager.Instance.IsPaused) return; // Already running
_isPaused = false;
StartBubbleBehavior(); StartBubbleBehavior();
// Debug log for troubleshooting // Debug log for troubleshooting
@@ -95,7 +87,7 @@ namespace Minigames.DivingForPictures
/// </summary> /// </summary>
private void StartBubbleBehavior() private void StartBubbleBehavior()
{ {
if (_isPaused || !isActiveAndEnabled) return; // Don't start if paused if (GameManager.Instance.IsPaused || !isActiveAndEnabled) return; // Don't start if paused
_movementCoroutine = StartCoroutine(MovementCoroutine()); _movementCoroutine = StartCoroutine(MovementCoroutine());
_wobbleCoroutine = StartCoroutine(WobbleCoroutine()); _wobbleCoroutine = StartCoroutine(WobbleCoroutine());

View File

@@ -25,15 +25,9 @@ namespace Minigames.DivingForPictures
private UnityEngine.Camera _mainCamera; // Cache camera reference private UnityEngine.Camera _mainCamera; // Cache camera reference
private bool _isSurfacing = false; private bool _isSurfacing = false;
// Pause state
private bool _isPaused = false;
// Coroutines for pause/resume // Coroutines for pause/resume
private Coroutine _spawnCoroutine; private Coroutine _spawnCoroutine;
// IPausable implementation
public bool IsPaused => _isPaused;
void Awake() void Awake()
{ {
_mainCamera = UnityEngine.Camera.main; _mainCamera = UnityEngine.Camera.main;
@@ -87,9 +81,7 @@ namespace Minigames.DivingForPictures
/// </summary> /// </summary>
public void Pause() public void Pause()
{ {
if (_isPaused) return; // Already paused if (GameManager.Instance.IsPaused) return; // Already paused
_isPaused = true;
// Stop spawning coroutine // Stop spawning coroutine
if (_spawnCoroutine != null) if (_spawnCoroutine != null)
@@ -116,9 +108,7 @@ namespace Minigames.DivingForPictures
/// </summary> /// </summary>
public void DoResume() public void DoResume()
{ {
if (!_isPaused) return; // Already running if (!GameManager.Instance.IsPaused) return; // Already running
_isPaused = false;
// Restart spawning coroutine // Restart spawning coroutine
StartSpawningCoroutine(); StartSpawningCoroutine();
@@ -141,7 +131,7 @@ namespace Minigames.DivingForPictures
/// </summary> /// </summary>
private void StartSpawningCoroutine() private void StartSpawningCoroutine()
{ {
if (_spawnCoroutine == null && !_isPaused) if (_spawnCoroutine == null && !GameManager.Instance.IsPaused)
{ {
_spawnCoroutine = StartCoroutine(SpawnBubblesRoutine()); _spawnCoroutine = StartCoroutine(SpawnBubblesRoutine());
} }
@@ -219,7 +209,7 @@ namespace Minigames.DivingForPictures
bubble.SetWobbleScaleLimits(_devSettings.BubbleWobbleMinScale, _devSettings.BubbleWobbleMaxScale); bubble.SetWobbleScaleLimits(_devSettings.BubbleWobbleMinScale, _devSettings.BubbleWobbleMaxScale);
// If the game is already paused, pause this bubble immediately // If the game is already paused, pause this bubble immediately
if (_isPaused) if (GameManager.Instance.IsPaused)
{ {
bubble.Pause(); bubble.Pause();
} }
@@ -262,7 +252,7 @@ namespace Minigames.DivingForPictures
{ {
Logging.Debug("[BubbleSpawner] Started bubble spawning coroutine"); Logging.Debug("[BubbleSpawner] Started bubble spawning coroutine");
while (enabled && gameObject.activeInHierarchy && !_isPaused) while (enabled && gameObject.activeInHierarchy && !GameManager.Instance.IsPaused)
{ {
SpawnBubble(); SpawnBubble();
SetNextSpawnInterval(); // Set interval for next spawn SetNextSpawnInterval(); // Set interval for next spawn

View File

@@ -7,7 +7,7 @@ using Minigames.DivingForPictures.PictureCamera;
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using Bootstrap;
using UI; using UI;
using UnityEngine; using UnityEngine;
using UnityEngine.Events; using UnityEngine.Events;
@@ -38,24 +38,24 @@ namespace Minigames.DivingForPictures
public CameraViewfinderManager viewfinderManager; public CameraViewfinderManager viewfinderManager;
// Settings reference // Settings reference
private IDivingMinigameSettings settings; private IDivingMinigameSettings _settings;
// Private state variables // Private state variables
private int playerScore = 0; private int _playerScore = 0;
private float currentSpawnProbability; private float _currentSpawnProbability;
private float lastSpawnTime = -100f; private float _lastSpawnTime = -100f;
private float timeSinceLastSpawn = 0f; private float _timeSinceLastSpawn = 0f;
private List<Monster> activeMonsters = new List<Monster>(); private List<Monster> _activeMonsters = new List<Monster>();
// Velocity management // Velocity management
// Velocity state tracking // Velocity state tracking
private float currentVelocityFactor = 1.0f; // 1.0 = normal descent speed, -1.0 * surfacingSpeedFactor = full surfacing speed private float _currentVelocityFactor = 1.0f; // 1.0 = normal descent speed, -1.0 * surfacingSpeedFactor = full surfacing speed
private Coroutine velocityTransitionCoroutine; private Coroutine _velocityTransitionCoroutine;
private Coroutine surfacingSequenceCoroutine; private Coroutine _surfacingSequenceCoroutine;
// Public properties // Public properties
public int PlayerScore => playerScore; public int PlayerScore => _playerScore;
public float CurrentVelocityFactor => currentVelocityFactor; public float CurrentVelocityFactor => _currentVelocityFactor;
// Events // Events
public event Action<int> OnScoreChanged; public event Action<int> OnScoreChanged;
@@ -67,8 +67,8 @@ namespace Minigames.DivingForPictures
public event Action<float> OnVelocityFactorChanged; public event Action<float> OnVelocityFactorChanged;
// Private state variables for rope system // Private state variables for rope system
private int currentRopeIndex = 0; private int _currentRopeIndex = 0;
private bool isGameOver = false; private bool _isGameOver = false;
private bool _isSurfacing = false; private bool _isSurfacing = false;
// Initialization state // Initialization state
@@ -77,23 +77,17 @@ namespace Minigames.DivingForPictures
// Used to track if we're currently surfacing // Used to track if we're currently surfacing
public bool IsSurfacing => _isSurfacing; public bool IsSurfacing => _isSurfacing;
// Event for game components to subscribe to // TODO: Get rid of this in favor of proper game pausing?
public event Action OnGameInitialized; public event Action OnGameInitialized;
// Pause state
private bool _isPaused = false;
// List of pausable components controlled by this manager // List of pausable components controlled by this manager
private List<IPausable> _pausableComponents = new List<IPausable>(); private List<IPausable> _pausableComponents = new List<IPausable>();
// IPausable implementation
public bool IsPaused => _isPaused;
// Photo sequence state // Photo sequence state
private bool _isPhotoSequenceActive = false; private bool _isPhotoSequenceActive = false;
private Monster _currentPhotoTarget = null; private Monster _currentPhotoTarget = null;
private Dictionary<IPausable, bool> _pauseStateBackup = new Dictionary<IPausable, bool>(); private float _capturedProximity = 0f;
private float _capturedProximity = 0f; // New: tracks how close to target the photo was taken (0-1)
// List of components to exempt from pausing during photo sequence // List of components to exempt from pausing during photo sequence
private List<IPausable> _exemptFromPhotoSequencePausing = new List<IPausable>(); private List<IPausable> _exemptFromPhotoSequencePausing = new List<IPausable>();
@@ -101,7 +95,6 @@ namespace Minigames.DivingForPictures
// Photo sequence events // Photo sequence events
public event Action<Monster> OnPhotoSequenceStarted; public event Action<Monster> OnPhotoSequenceStarted;
public event Action<Monster, float> OnPhotoSequenceCompleted; // Now includes proximity score public event Action<Monster, float> OnPhotoSequenceCompleted; // Now includes proximity score
public event Action<float> OnPhotoSequenceProgressUpdated;
private static DivingGameManager _instance = null; private static DivingGameManager _instance = null;
private static bool _isQuitting = false; private static bool _isQuitting = false;
@@ -113,8 +106,8 @@ namespace Minigames.DivingForPictures
private void Awake() private void Awake()
{ {
settings = GameManager.GetSettingsObject<IDivingMinigameSettings>(); _settings = GameManager.GetSettingsObject<IDivingMinigameSettings>();
currentSpawnProbability = settings?.BaseSpawnProbability ?? 0.2f; _currentSpawnProbability = _settings?.BaseSpawnProbability ?? 0.2f;
if (_instance == null) if (_instance == null)
{ {
@@ -133,44 +126,8 @@ namespace Minigames.DivingForPictures
private void Start() private void Start()
{ {
// Find PauseMenu and subscribe to its events // Register for post-boot initialization
PauseMenu pauseMenu = PauseMenu.Instance; BootCompletionService.RegisterInitAction(InitializePostBoot);
if (pauseMenu != null)
{
pauseMenu.OnGamePaused += Pause;
pauseMenu.OnGameResumed += DoResume;
Logging.Debug("[DivingGameManager] Subscribed to PauseMenu events");
}
else
{
Logging.Warning("[DivingGameManager] PauseMenu not found. Pause functionality won't work properly.");
}
// Register this manager with the global GameManager
if (GameManager.Instance != null)
{
GameManager.Instance.RegisterPausableComponent(this);
}
// Subscribe to SceneOrientationEnforcer's event
if (SceneOrientationEnforcer.Instance != null)
{
SceneOrientationEnforcer.Instance.OnOrientationCorrect += InitializeGame;
SceneOrientationEnforcer.Instance.OnOrientationIncorrect += Pause;
// If orientation is already correct, initialize right away
// This prevents issues if the orientation was already correct before subscription
if (SceneOrientationEnforcer.Instance.IsOrientationCorrect())
{
InitializeGame();
}
}
else
{
Logging.Warning("[DivingGameManager] SceneOrientationEnforcer not found. Initializing game immediately.");
InitializeGame();
}
// Subscribe to player damage events (this doesn't depend on initialization) // Subscribe to player damage events (this doesn't depend on initialization)
PlayerCollisionBehavior.OnDamageTaken += OnPlayerDamageTaken; PlayerCollisionBehavior.OnDamageTaken += OnPlayerDamageTaken;
@@ -189,6 +146,7 @@ namespace Minigames.DivingForPictures
viewfinderManager.OnViewfinderTappedDuringAnimation += OnViewfinderTappedDuringAnimation; viewfinderManager.OnViewfinderTappedDuringAnimation += OnViewfinderTappedDuringAnimation;
viewfinderManager.OnReverseAnimationStarted += OnReverseAnimationStarted; viewfinderManager.OnReverseAnimationStarted += OnReverseAnimationStarted;
// TODO: Give this a second look and make sure this is correct
// Add the viewfinder manager to exempt list to ensure it keeps working during photo sequences // Add the viewfinder manager to exempt list to ensure it keeps working during photo sequences
if (viewfinderManager is IPausable viewfinderPausable) if (viewfinderManager is IPausable viewfinderPausable)
{ {
@@ -197,6 +155,36 @@ namespace Minigames.DivingForPictures
} }
OnMonsterSpawned += DoMonsterSpawned; OnMonsterSpawned += DoMonsterSpawned;
}
private void InitializePostBoot()
{
// Register this manager with the global GameManager
if (GameManager.Instance != null)
{
GameManager.Instance.RegisterPausableComponent(this);
}
// Subscribe to SceneOrientationEnforcer's event
if (SceneOrientationEnforcer.Instance != null)
{
// TODO: This is a bit of a hack to make sure the game is initialized after the orientation is correct
SceneOrientationEnforcer.Instance.OnOrientationCorrect += InitializeGame;
SceneOrientationEnforcer.Instance.OnOrientationIncorrect += Pause;
// If orientation is already correct, initialize right away
// This prevents issues if the orientation was already correct before subscription
if (SceneOrientationEnforcer.Instance.IsOrientationCorrect())
{
InitializeGame();
}
}
else
{
Logging.Warning("[DivingGameManager] SceneOrientationEnforcer not found. Initializing game immediately.");
InitializeGame();
}
CinematicsManager.Instance.OnCinematicStopped += EndGame; CinematicsManager.Instance.OnCinematicStopped += EndGame;
} }
@@ -211,14 +199,6 @@ namespace Minigames.DivingForPictures
SceneOrientationEnforcer.Instance.OnOrientationIncorrect -= Pause; SceneOrientationEnforcer.Instance.OnOrientationIncorrect -= Pause;
} }
// Unsubscribe from PauseMenu events
PauseMenu pauseMenu = PauseMenu.Instance;
if (pauseMenu != null)
{
pauseMenu.OnGamePaused -= Pause;
pauseMenu.OnGameResumed -= DoResume;
}
// Unregister from GameManager // Unregister from GameManager
if (GameManager.Instance != null) if (GameManager.Instance != null)
{ {
@@ -241,19 +221,19 @@ namespace Minigames.DivingForPictures
private void Update() private void Update()
{ {
timeSinceLastSpawn += Time.deltaTime; _timeSinceLastSpawn += Time.deltaTime;
// Gradually increase spawn probability over time // Gradually increase spawn probability over time
float previousProbability = currentSpawnProbability; float previousProbability = _currentSpawnProbability;
if (currentSpawnProbability < settings.MaxSpawnProbability) if (_currentSpawnProbability < _settings.MaxSpawnProbability)
{ {
currentSpawnProbability += settings.ProbabilityIncreaseRate * Time.deltaTime; _currentSpawnProbability += _settings.ProbabilityIncreaseRate * Time.deltaTime;
currentSpawnProbability = Mathf.Min(currentSpawnProbability, settings.MaxSpawnProbability); _currentSpawnProbability = Mathf.Min(_currentSpawnProbability, _settings.MaxSpawnProbability);
// Only fire event if probability changed significantly // Only fire event if probability changed significantly
if (Mathf.Abs(currentSpawnProbability - previousProbability) > 0.01f) if (Mathf.Abs(_currentSpawnProbability - previousProbability) > 0.01f)
{ {
OnSpawnProbabilityChanged?.Invoke(currentSpawnProbability); OnSpawnProbabilityChanged?.Invoke(_currentSpawnProbability);
} }
} }
} }
@@ -268,14 +248,14 @@ namespace Minigames.DivingForPictures
// If we're surfacing, don't spawn new monsters // If we're surfacing, don't spawn new monsters
if (_isSurfacing) return; if (_isSurfacing) return;
bool forceSpawn = timeSinceLastSpawn >= settings.GuaranteedSpawnTime; bool forceSpawn = _timeSinceLastSpawn >= _settings.GuaranteedSpawnTime;
bool onCooldown = timeSinceLastSpawn < settings.SpawnCooldown; bool onCooldown = _timeSinceLastSpawn < _settings.SpawnCooldown;
// Don't spawn if on cooldown, unless forced // Don't spawn if on cooldown, unless forced
if (onCooldown && !forceSpawn) return; if (onCooldown && !forceSpawn) return;
// Check probability or forced spawn // Check probability or forced spawn
if (forceSpawn || UnityEngine.Random.value <= currentSpawnProbability) if (forceSpawn || UnityEngine.Random.value <= _currentSpawnProbability)
{ {
// Pick a random spawn point from this tile // Pick a random spawn point from this tile
MonsterSpawnPoint spawnPoint = spawnPoints[UnityEngine.Random.Range(0, spawnPoints.Length)]; MonsterSpawnPoint spawnPoint = spawnPoints[UnityEngine.Random.Range(0, spawnPoints.Length)];
@@ -284,10 +264,10 @@ namespace Minigames.DivingForPictures
SpawnMonster(spawnPoint.transform); SpawnMonster(spawnPoint.transform);
// Reset timer and adjust probability // Reset timer and adjust probability
lastSpawnTime = Time.time; _lastSpawnTime = Time.time;
timeSinceLastSpawn = 0f; _timeSinceLastSpawn = 0f;
currentSpawnProbability = settings.BaseSpawnProbability; _currentSpawnProbability = _settings.BaseSpawnProbability;
OnSpawnProbabilityChanged?.Invoke(currentSpawnProbability); OnSpawnProbabilityChanged?.Invoke(_currentSpawnProbability);
} }
} }
@@ -335,14 +315,14 @@ namespace Minigames.DivingForPictures
private void DoPictureTaken(Monster monster) private void DoPictureTaken(Monster monster)
{ {
// Calculate points based on depth // Calculate points based on depth
int depthBonus = Mathf.FloorToInt(Mathf.Abs(monster.transform.position.y) * settings.DepthMultiplier); int depthBonus = Mathf.FloorToInt(Mathf.Abs(monster.transform.position.y) * _settings.DepthMultiplier);
int pointsAwarded = settings.BasePoints + depthBonus; int pointsAwarded = _settings.BasePoints + depthBonus;
// Add score // Add score
playerScore += pointsAwarded; _playerScore += pointsAwarded;
// Fire events // Fire events
OnScoreChanged?.Invoke(playerScore); OnScoreChanged?.Invoke(_playerScore);
OnPictureTaken?.Invoke(monster, pointsAwarded); OnPictureTaken?.Invoke(monster, pointsAwarded);
} }
@@ -351,13 +331,13 @@ namespace Minigames.DivingForPictures
/// </summary> /// </summary>
private void OnPlayerDamageTaken() private void OnPlayerDamageTaken()
{ {
if (isGameOver) return; if (_isGameOver) return;
// Break the next rope in sequence // Break the next rope in sequence
BreakNextRope(); BreakNextRope();
// Check if all ropes are broken // Check if all ropes are broken
if (currentRopeIndex >= playerRopes.Length) if (_currentRopeIndex >= playerRopes.Length)
{ {
TriggerGameOver(); TriggerGameOver();
deathAudioPlayer.Play(); deathAudioPlayer.Play();
@@ -365,7 +345,7 @@ namespace Minigames.DivingForPictures
else else
{ {
// Notify listeners about rope break and remaining ropes // Notify listeners about rope break and remaining ropes
int remainingRopes = playerRopes.Length - currentRopeIndex; int remainingRopes = playerRopes.Length - _currentRopeIndex;
OnRopeBroken?.Invoke(remainingRopes); OnRopeBroken?.Invoke(remainingRopes);
Logging.Debug($"[DivingGameManager] Rope broken! {remainingRopes} ropes remaining."); Logging.Debug($"[DivingGameManager] Rope broken! {remainingRopes} ropes remaining.");
@@ -377,9 +357,9 @@ namespace Minigames.DivingForPictures
/// </summary> /// </summary>
private void BreakNextRope() private void BreakNextRope()
{ {
if (currentRopeIndex < playerRopes.Length) if (_currentRopeIndex < playerRopes.Length)
{ {
RopeBreaker ropeToBreak = playerRopes[currentRopeIndex]; RopeBreaker ropeToBreak = playerRopes[_currentRopeIndex];
if (ropeToBreak != null) if (ropeToBreak != null)
{ {
@@ -388,11 +368,11 @@ namespace Minigames.DivingForPictures
} }
else else
{ {
Logging.Warning($"[DivingGameManager] Rope at index {currentRopeIndex} is null!"); Logging.Warning($"[DivingGameManager] Rope at index {_currentRopeIndex} is null!");
} }
// Move to the next rope regardless if current was null // Move to the next rope regardless if current was null
currentRopeIndex++; _currentRopeIndex++;
} }
} }
@@ -401,7 +381,7 @@ namespace Minigames.DivingForPictures
/// </summary> /// </summary>
public void ForceBreakRope() public void ForceBreakRope()
{ {
if (!isGameOver) if (!_isGameOver)
{ {
OnPlayerDamageTaken(); OnPlayerDamageTaken();
} }
@@ -412,9 +392,9 @@ namespace Minigames.DivingForPictures
/// </summary> /// </summary>
private void TriggerGameOver() private void TriggerGameOver()
{ {
if (isGameOver) return; if (_isGameOver) return;
isGameOver = true; _isGameOver = true;
Logging.Debug("[DivingGameManager] Game Over! All ropes broken. Starting surfacing sequence..."); Logging.Debug("[DivingGameManager] Game Over! All ropes broken. Starting surfacing sequence...");
// Fire game over event // Fire game over event
@@ -450,8 +430,8 @@ namespace Minigames.DivingForPictures
public void ResetRopeSystem() public void ResetRopeSystem()
{ {
// Reset rope state // Reset rope state
currentRopeIndex = 0; _currentRopeIndex = 0;
isGameOver = false; _isGameOver = false;
// Restore all broken ropes // Restore all broken ropes
if (playerRopes != null) if (playerRopes != null)
@@ -478,7 +458,7 @@ namespace Minigames.DivingForPictures
_isSurfacing = true; _isSurfacing = true;
// 1. Initiate smooth velocity transition to surfacing speed // 1. Initiate smooth velocity transition to surfacing speed
float targetVelocityFactor = -1.0f * settings.SurfacingSpeedFactor; float targetVelocityFactor = -1.0f * _settings.SurfacingSpeedFactor;
SetVelocityFactor(targetVelocityFactor); SetVelocityFactor(targetVelocityFactor);
// 2. Find and notify trench tile spawner about direction change (for spawning/despawning logic) // 2. Find and notify trench tile spawner about direction change (for spawning/despawning logic)
@@ -497,7 +477,7 @@ namespace Minigames.DivingForPictures
tileSpawner.StartSurfacing(); tileSpawner.StartSurfacing();
// Immediately send current velocity factor // Immediately send current velocity factor
tileSpawner.OnVelocityFactorChanged(currentVelocityFactor); tileSpawner.OnVelocityFactorChanged(_currentVelocityFactor);
} }
// Handle the Rock object - disable components and animate it falling offscreen // Handle the Rock object - disable components and animate it falling offscreen
@@ -565,15 +545,15 @@ namespace Minigames.DivingForPictures
obstacleSpawner.StartSurfacing(); obstacleSpawner.StartSurfacing();
// Immediately send current velocity factor // Immediately send current velocity factor
obstacleSpawner.OnVelocityFactorChanged(currentVelocityFactor); obstacleSpawner.OnVelocityFactorChanged(_currentVelocityFactor);
} }
// Start the surfacing sequence coroutine // Start the surfacing sequence coroutine
if (surfacingSequenceCoroutine != null) if (_surfacingSequenceCoroutine != null)
{ {
StopCoroutine(surfacingSequenceCoroutine); StopCoroutine(_surfacingSequenceCoroutine);
} }
surfacingSequenceCoroutine = StartCoroutine(SurfacingSequence()); _surfacingSequenceCoroutine = StartCoroutine(SurfacingSequence());
Logging.Debug($"[DivingGameManager] Started surfacing with target velocity factor: {targetVelocityFactor}"); Logging.Debug($"[DivingGameManager] Started surfacing with target velocity factor: {targetVelocityFactor}");
} }
@@ -649,7 +629,7 @@ namespace Minigames.DivingForPictures
private IEnumerator SurfacingSequence() private IEnumerator SurfacingSequence()
{ {
// Wait for the configured delay // Wait for the configured delay
yield return new WaitForSeconds(settings.SurfacingSpawnDelay); yield return new WaitForSeconds(_settings.SurfacingSpawnDelay);
// Find tile spawner and tell it to stop spawning // Find tile spawner and tell it to stop spawning
TrenchTileSpawner tileSpawner = FindFirstObjectByType<TrenchTileSpawner>(); TrenchTileSpawner tileSpawner = FindFirstObjectByType<TrenchTileSpawner>();
@@ -686,7 +666,6 @@ namespace Minigames.DivingForPictures
// Call this when the game ends // Call this when the game ends
public void EndGame() public void EndGame()
{ {
// TODO: Investigate why called twice
CinematicsManager.Instance.OnCinematicStopped -= EndGame; CinematicsManager.Instance.OnCinematicStopped -= EndGame;
// Start the end game sequence that grants a booster, waits for the UI animation, then shows Game Over. // Start the end game sequence that grants a booster, waits for the UI animation, then shows Game Over.
StartCoroutine(EndGameSequence()); StartCoroutine(EndGameSequence());
@@ -695,7 +674,7 @@ namespace Minigames.DivingForPictures
private IEnumerator EndGameSequence() private IEnumerator EndGameSequence()
{ {
// Clean up active monsters // Clean up active monsters
foreach (var monster in activeMonsters.ToArray()) foreach (var monster in _activeMonsters.ToArray())
{ {
if (monster != null) if (monster != null)
{ {
@@ -703,7 +682,7 @@ namespace Minigames.DivingForPictures
} }
} }
activeMonsters.Clear(); _activeMonsters.Clear();
// 1) Call the booster pack giver if available // 1) Call the booster pack giver if available
bool completed = false; bool completed = false;
@@ -735,7 +714,7 @@ namespace Minigames.DivingForPictures
CinematicsManager.Instance.ShowGameOverScreen(); CinematicsManager.Instance.ShowGameOverScreen();
// Final score could be saved to player prefs or other persistence // Final score could be saved to player prefs or other persistence
Logging.Debug($"Final Score: {playerScore}"); Logging.Debug($"Final Score: {_playerScore}");
} }
/// <summary> /// <summary>
@@ -744,12 +723,12 @@ namespace Minigames.DivingForPictures
/// <param name="targetFactor">Target velocity factor (e.g., -1.0 for surfacing speed)</param> /// <param name="targetFactor">Target velocity factor (e.g., -1.0 for surfacing speed)</param>
public void SetVelocityFactor(float targetFactor) public void SetVelocityFactor(float targetFactor)
{ {
if (velocityTransitionCoroutine != null) if (_velocityTransitionCoroutine != null)
{ {
StopCoroutine(velocityTransitionCoroutine); StopCoroutine(_velocityTransitionCoroutine);
} }
velocityTransitionCoroutine = StartCoroutine(TransitionVelocityFactor(targetFactor)); _velocityTransitionCoroutine = StartCoroutine(TransitionVelocityFactor(targetFactor));
} }
/// <summary> /// <summary>
@@ -757,29 +736,29 @@ namespace Minigames.DivingForPictures
/// </summary> /// </summary>
private IEnumerator<WaitForEndOfFrame> TransitionVelocityFactor(float targetFactor) private IEnumerator<WaitForEndOfFrame> TransitionVelocityFactor(float targetFactor)
{ {
float startFactor = currentVelocityFactor; float startFactor = _currentVelocityFactor;
float elapsed = 0f; float elapsed = 0f;
while (elapsed < settings.SpeedTransitionDuration) while (elapsed < _settings.SpeedTransitionDuration)
{ {
elapsed += Time.deltaTime; elapsed += Time.deltaTime;
float t = Mathf.Clamp01(elapsed / settings.SpeedTransitionDuration); float t = Mathf.Clamp01(elapsed / _settings.SpeedTransitionDuration);
// Smooth step interpolation // Smooth step interpolation
float smoothStep = t * t * (3f - 2f * t); float smoothStep = t * t * (3f - 2f * t);
currentVelocityFactor = Mathf.Lerp(startFactor, targetFactor, smoothStep); _currentVelocityFactor = Mathf.Lerp(startFactor, targetFactor, smoothStep);
// Notify listeners about the velocity factor change // Notify listeners about the velocity factor change
OnVelocityFactorChanged?.Invoke(currentVelocityFactor); OnVelocityFactorChanged?.Invoke(_currentVelocityFactor);
yield return null; yield return null;
} }
currentVelocityFactor = targetFactor; _currentVelocityFactor = targetFactor;
// Final assignment to ensure exact target value // Final assignment to ensure exact target value
OnVelocityFactorChanged?.Invoke(currentVelocityFactor); OnVelocityFactorChanged?.Invoke(_currentVelocityFactor);
} }
/// <summary> /// <summary>
@@ -793,7 +772,7 @@ namespace Minigames.DivingForPictures
_pausableComponents.Add(component); _pausableComponents.Add(component);
// If the game is already paused, pause the component immediately // If the game is already paused, pause the component immediately
if (_isPaused) if (GameManager.Instance.IsPaused)
{ {
component.Pause(); component.Pause();
} }
@@ -825,9 +804,7 @@ namespace Minigames.DivingForPictures
public void DoPause(bool turnOffGameInput = true) public void DoPause(bool turnOffGameInput = true)
{ {
if (_isPaused) return; // Already paused if (GameManager.Instance.IsPaused) return; // Already paused
_isPaused = true;
// Pause all registered components // Pause all registered components
foreach (var component in _pausableComponents) foreach (var component in _pausableComponents)
@@ -847,9 +824,7 @@ namespace Minigames.DivingForPictures
/// </summary> /// </summary>
public void DoResume() public void DoResume()
{ {
if (!_isPaused) return; // Already running if (!GameManager.Instance.IsPaused) return; // Already running
_isPaused = false;
// Resume all registered components // Resume all registered components
foreach (var component in _pausableComponents) foreach (var component in _pausableComponents)
@@ -938,23 +913,23 @@ namespace Minigames.DivingForPictures
if (monster == null) return; if (monster == null) return;
// Calculate base points from depth // Calculate base points from depth
int depthBonus = Mathf.FloorToInt(Mathf.Abs(monster.transform.position.y) * settings.DepthMultiplier); int depthBonus = Mathf.FloorToInt(Mathf.Abs(monster.transform.position.y) * _settings.DepthMultiplier);
// Apply proximity multiplier (0-100%) // Apply proximity multiplier (0-100%)
float proximityMultiplier = Mathf.Clamp01(proximity); // Ensure it's in 0-1 range float proximityMultiplier = Mathf.Clamp01(proximity); // Ensure it's in 0-1 range
int proximityBonus = Mathf.RoundToInt(settings.BasePoints * proximityMultiplier); int proximityBonus = Mathf.RoundToInt(_settings.BasePoints * proximityMultiplier);
// Calculate total score // Calculate total score
int pointsAwarded = settings.BasePoints + proximityBonus + depthBonus; int pointsAwarded = _settings.BasePoints + proximityBonus + depthBonus;
Logging.Debug($"[DivingGameManager] Picture score calculation: base={proximityBonus} (proximity={proximity:F2}), " + Logging.Debug($"[DivingGameManager] Picture score calculation: base={proximityBonus} (proximity={proximity:F2}), " +
$"depth bonus={depthBonus}, total={pointsAwarded}"); $"depth bonus={depthBonus}, total={pointsAwarded}");
// Add score // Add score
playerScore += pointsAwarded; _playerScore += pointsAwarded;
// Fire events // Fire events
OnScoreChanged?.Invoke(playerScore); OnScoreChanged?.Invoke(_playerScore);
OnPictureTaken?.Invoke(monster, pointsAwarded); OnPictureTaken?.Invoke(monster, pointsAwarded);
} }
@@ -1061,14 +1036,14 @@ namespace Minigames.DivingForPictures
monster.OnMonsterDespawned += DoMonsterDespawned; monster.OnMonsterDespawned += DoMonsterDespawned;
// Add to active monsters list // Add to active monsters list
activeMonsters.Add(monster); _activeMonsters.Add(monster);
} }
} }
private void DoMonsterDespawned(Monster monster) private void DoMonsterDespawned(Monster monster)
{ {
// Remove from active list // Remove from active list
activeMonsters.Remove(monster); _activeMonsters.Remove(monster);
// Unsubscribe from monster events // Unsubscribe from monster events
if (monster != null) if (monster != null)

View File

@@ -59,12 +59,6 @@ namespace Minigames.DivingForPictures
private float _screenNormalizationFactor = 1.0f; private float _screenNormalizationFactor = 1.0f;
private IDivingMinigameSettings _settings; private IDivingMinigameSettings _settings;
// Pause state
private bool _isPaused = false;
// IPausable implementation
public bool IsPaused => _isPaused;
private void Awake() private void Awake()
{ {
_collider = GetComponent<Collider2D>(); _collider = GetComponent<Collider2D>();
@@ -124,7 +118,7 @@ namespace Minigames.DivingForPictures
private void OnEnable() private void OnEnable()
{ {
// Only start coroutines if not paused // Only start coroutines if not paused
if (!_isPaused) if (!GameManager.Instance.IsPaused)
{ {
StartObstacleCoroutines(); StartObstacleCoroutines();
} }
@@ -143,9 +137,8 @@ namespace Minigames.DivingForPictures
/// </summary> /// </summary>
public void Pause() public void Pause()
{ {
if (_isPaused) return; // Already paused if (GameManager.Instance.IsPaused) return; // Already paused
_isPaused = true;
StopObstacleCoroutines(); StopObstacleCoroutines();
Logging.Debug($"[FloatingObstacle] Paused obstacle: {name}"); Logging.Debug($"[FloatingObstacle] Paused obstacle: {name}");
@@ -156,9 +149,8 @@ namespace Minigames.DivingForPictures
/// </summary> /// </summary>
public void DoResume() public void DoResume()
{ {
if (!_isPaused) return; // Already running if (!GameManager.Instance.IsPaused) return; // Already running
_isPaused = false;
StartObstacleCoroutines(); StartObstacleCoroutines();
Logging.Debug($"[FloatingObstacle] Resumed obstacle: {name}"); Logging.Debug($"[FloatingObstacle] Resumed obstacle: {name}");

View File

@@ -43,12 +43,6 @@ namespace Minigames.DivingForPictures
private bool _isSurfacing = false; // Flag to track surfacing state private bool _isSurfacing = false; // Flag to track surfacing state
private float _velocityFactor = 1.0f; // Current velocity factor from the game manager private float _velocityFactor = 1.0f; // Current velocity factor from the game manager
// Pause state
private bool _isPaused = false;
// IPausable implementation
public bool IsPaused => _isPaused;
private void Awake() private void Awake()
{ {
_mainCamera = UnityEngine.Camera.main; _mainCamera = UnityEngine.Camera.main;
@@ -127,9 +121,7 @@ namespace Minigames.DivingForPictures
/// </summary> /// </summary>
public void Pause() public void Pause()
{ {
if (_isPaused) return; // Already paused if (GameManager.Instance.IsPaused) return; // Already paused
_isPaused = true;
// Stop spawning coroutine // Stop spawning coroutine
if (_spawnCoroutine != null) if (_spawnCoroutine != null)
@@ -159,9 +151,8 @@ namespace Minigames.DivingForPictures
/// </summary> /// </summary>
public void DoResume() public void DoResume()
{ {
if (!_isPaused) return; // Already running if (!GameManager.Instance.IsPaused) return; // Already running
_isPaused = false;
// Restart spawning coroutine if not in surfacing mode // Restart spawning coroutine if not in surfacing mode
if (!_isSurfacing) if (!_isSurfacing)
@@ -190,7 +181,7 @@ namespace Minigames.DivingForPictures
/// </summary> /// </summary>
private void StartSpawnCoroutine() private void StartSpawnCoroutine()
{ {
if (_spawnCoroutine == null && !_isPaused && !_isSurfacing) if (_spawnCoroutine == null && !GameManager.Instance.IsPaused && !_isSurfacing)
{ {
_spawnCoroutine = StartCoroutine(SpawnObstacleRoutine()); _spawnCoroutine = StartCoroutine(SpawnObstacleRoutine());
} }
@@ -201,7 +192,7 @@ namespace Minigames.DivingForPictures
/// </summary> /// </summary>
private void StartMoveCoroutine() private void StartMoveCoroutine()
{ {
if (_moveCoroutine == null && !_isPaused) if (_moveCoroutine == null && !GameManager.Instance.IsPaused)
{ {
_moveCoroutine = StartCoroutine(MoveObstaclesRoutine()); _moveCoroutine = StartCoroutine(MoveObstaclesRoutine());
} }
@@ -212,7 +203,7 @@ namespace Minigames.DivingForPictures
/// </summary> /// </summary>
private void StartDespawnCoroutine() private void StartDespawnCoroutine()
{ {
if (_despawnCoroutine == null && !_isPaused) if (_despawnCoroutine == null && !GameManager.Instance.IsPaused)
{ {
_despawnCoroutine = StartCoroutine(DespawnObstaclesRoutine()); _despawnCoroutine = StartCoroutine(DespawnObstaclesRoutine());
} }
@@ -553,7 +544,7 @@ namespace Minigames.DivingForPictures
obstacleComponent.SetSpawner(this); obstacleComponent.SetSpawner(this);
// If spawner is already paused, pause the obstacle immediately // If spawner is already paused, pause the obstacle immediately
if (_isPaused) if (GameManager.Instance.IsPaused)
{ {
obstacleComponent.Pause(); obstacleComponent.Pause();
} }
@@ -677,7 +668,7 @@ namespace Minigames.DivingForPictures
{ {
Logging.Debug("[ObstacleSpawner] Started spawning coroutine"); Logging.Debug("[ObstacleSpawner] Started spawning coroutine");
while (enabled && gameObject.activeInHierarchy && !_isPaused && !_isSurfacing) while (enabled && gameObject.activeInHierarchy && !GameManager.Instance.IsPaused && !_isSurfacing)
{ {
// Calculate next spawn time with variation // Calculate next spawn time with variation
float nextSpawnTime = _settings.ObstacleSpawnInterval + float nextSpawnTime = _settings.ObstacleSpawnInterval +
@@ -707,7 +698,7 @@ namespace Minigames.DivingForPictures
Logging.Debug("[ObstacleSpawner] Started obstacle monitoring coroutine"); Logging.Debug("[ObstacleSpawner] Started obstacle monitoring coroutine");
// This coroutine now just monitors obstacles, not moves them // This coroutine now just monitors obstacles, not moves them
while (enabled && gameObject.activeInHierarchy && !_isPaused) while (enabled && gameObject.activeInHierarchy && !GameManager.Instance.IsPaused)
{ {
// Clean up any null references in the active obstacles list // Clean up any null references in the active obstacles list
_activeObstacles.RemoveAll(obstacle => obstacle == null); _activeObstacles.RemoveAll(obstacle => obstacle == null);
@@ -729,7 +720,7 @@ namespace Minigames.DivingForPictures
const float checkInterval = 0.5f; // Check every half second const float checkInterval = 0.5f; // Check every half second
Logging.Debug("[ObstacleSpawner] Started despawn coroutine with interval: " + checkInterval); Logging.Debug("[ObstacleSpawner] Started despawn coroutine with interval: " + checkInterval);
while (enabled && gameObject.activeInHierarchy && !_isPaused) while (enabled && gameObject.activeInHierarchy && !GameManager.Instance.IsPaused)
{ {
// Calculate screen bounds for despawning // Calculate screen bounds for despawning
float despawnBuffer = 2f; // Extra buffer beyond screen edges float despawnBuffer = 2f; // Extra buffer beyond screen edges

View File

@@ -18,26 +18,26 @@ namespace Minigames.DivingForPictures.Player
[SerializeField] private EdgeAnchor edgeAnchor; [SerializeField] private EdgeAnchor edgeAnchor;
// Settings reference // Settings reference
private IDivingMinigameSettings settings; private IDivingMinigameSettings _settings;
private float targetFingerX; private float _targetFingerX;
private bool isTouchActive; private bool _isTouchActive;
private float originY; private float _originY;
// Tap impulse system variables // Tap impulse system variables
private float tapImpulseStrength = 0f; private float _tapImpulseStrength = 0f;
private float tapDirection = 0f; private float _tapDirection = 0f;
// Initialization flag // Initialization flag
private bool isInitialized = false; private bool _isInitialized = false;
void Awake() void Awake()
{ {
originY = transform.position.y; _originY = transform.position.y;
// Get settings from GameManager // Get settings from GameManager
settings = GameManager.GetSettingsObject<IDivingMinigameSettings>(); _settings = GameManager.GetSettingsObject<IDivingMinigameSettings>();
if (settings == null) if (_settings == null)
{ {
Debug.LogError("[PlayerController] Failed to load diving minigame settings!"); Debug.LogError("[PlayerController] Failed to load diving minigame settings!");
} }
@@ -49,8 +49,8 @@ namespace Minigames.DivingForPictures.Player
DivingGameManager.Instance.RegisterPausableComponent(this); DivingGameManager.Instance.RegisterPausableComponent(this);
// Initialize target to current position // Initialize target to current position
targetFingerX = transform.position.x; _targetFingerX = transform.position.x;
isTouchActive = false; _isTouchActive = false;
// Try to find edge anchor if not assigned // Try to find edge anchor if not assigned
if (edgeAnchor == null) if (edgeAnchor == null)
@@ -100,12 +100,12 @@ namespace Minigames.DivingForPictures.Player
/// </summary> /// </summary>
private void Initialize() private void Initialize()
{ {
if (isInitialized) return; if (_isInitialized) return;
// Register as default consumer for input // Register as default consumer for input
InputManager.Instance?.SetDefaultConsumer(this); InputManager.Instance?.SetDefaultConsumer(this);
isInitialized = true; _isInitialized = true;
Logging.Debug("[PlayerController] Initialized"); Logging.Debug("[PlayerController] Initialized");
} }
@@ -130,19 +130,19 @@ namespace Minigames.DivingForPictures.Player
public void OnTap(Vector2 worldPosition) public void OnTap(Vector2 worldPosition)
{ {
// Ignore input when paused // Ignore input when paused
if (isPaused) return; if (GameManager.Instance.IsPaused) return;
// Logging.Debug($"[EndlessDescenderController] OnTap at {worldPosition}"); // Logging.Debug($"[EndlessDescenderController] OnTap at {worldPosition}");
float targetX = Mathf.Clamp(worldPosition.x, settings.ClampXMin, settings.ClampXMax); float targetX = Mathf.Clamp(worldPosition.x, _settings.ClampXMin, _settings.ClampXMax);
// Calculate tap direction (+1 for right, -1 for left) // Calculate tap direction (+1 for right, -1 for left)
tapDirection = Mathf.Sign(targetX - transform.position.x); _tapDirection = Mathf.Sign(targetX - transform.position.x);
// Set impulse strength to full // Set impulse strength to full
tapImpulseStrength = 1.0f; _tapImpulseStrength = 1.0f;
// Store target X for animation purposes // Store target X for animation purposes
targetFingerX = targetX; _targetFingerX = targetX;
// Do not set _isTouchActive for taps anymore // Do not set _isTouchActive for taps anymore
// _isTouchActive = true; - Removed to prevent continuous movement // _isTouchActive = true; - Removed to prevent continuous movement
@@ -154,11 +154,11 @@ namespace Minigames.DivingForPictures.Player
public void OnHoldStart(Vector2 worldPosition) public void OnHoldStart(Vector2 worldPosition)
{ {
// Ignore input when paused // Ignore input when paused
if (isPaused) return; if (GameManager.Instance.IsPaused) return;
// Logging.Debug($"[EndlessDescenderController] OnHoldStart at {worldPosition}"); // Logging.Debug($"[EndlessDescenderController] OnHoldStart at {worldPosition}");
targetFingerX = Mathf.Clamp(worldPosition.x, settings.ClampXMin, settings.ClampXMax); _targetFingerX = Mathf.Clamp(worldPosition.x, _settings.ClampXMin, _settings.ClampXMax);
isTouchActive = true; _isTouchActive = true;
} }
/// <summary> /// <summary>
@@ -167,10 +167,10 @@ namespace Minigames.DivingForPictures.Player
public void OnHoldMove(Vector2 worldPosition) public void OnHoldMove(Vector2 worldPosition)
{ {
// Ignore input when paused // Ignore input when paused
if (isPaused) return; if (GameManager.Instance.IsPaused) return;
// Logging.Debug($"[EndlessDescenderController] OnHoldMove at {worldPosition}"); // Logging.Debug($"[EndlessDescenderController] OnHoldMove at {worldPosition}");
targetFingerX = Mathf.Clamp(worldPosition.x, settings.ClampXMin, settings.ClampXMax); _targetFingerX = Mathf.Clamp(worldPosition.x, _settings.ClampXMin, _settings.ClampXMax);
} }
/// <summary> /// <summary>
@@ -179,25 +179,25 @@ namespace Minigames.DivingForPictures.Player
public void OnHoldEnd(Vector2 worldPosition) public void OnHoldEnd(Vector2 worldPosition)
{ {
// Ignore input when paused // Ignore input when paused
if (isPaused) return; if (GameManager.Instance.IsPaused) return;
// Logging.Debug($"[EndlessDescenderController] OnHoldEnd at {worldPosition}"); // Logging.Debug($"[EndlessDescenderController] OnHoldEnd at {worldPosition}");
isTouchActive = false; _isTouchActive = false;
} }
void Update() void Update()
{ {
// Skip movement processing if paused // Skip movement processing if paused
if (isPaused) return; if (GameManager.Instance.IsPaused) return;
// Handle hold movement // Handle hold movement
if (isTouchActive) if (_isTouchActive)
{ {
float currentX = transform.position.x; float currentX = transform.position.x;
float lerpSpeed = settings.LerpSpeed; float lerpSpeed = _settings.LerpSpeed;
float maxOffset = settings.MaxOffset; float maxOffset = _settings.MaxOffset;
float exponent = settings.SpeedExponent; float exponent = _settings.SpeedExponent;
float targetX = targetFingerX; float targetX = _targetFingerX;
float offset = targetX - currentX; float offset = targetX - currentX;
offset = Mathf.Clamp(offset, -maxOffset, maxOffset); offset = Mathf.Clamp(offset, -maxOffset, maxOffset);
float absOffset = Mathf.Abs(offset); float absOffset = Mathf.Abs(offset);
@@ -206,32 +206,32 @@ namespace Minigames.DivingForPictures.Player
// Prevent overshooting // Prevent overshooting
moveStep = Mathf.Clamp(moveStep, -absOffset, absOffset); moveStep = Mathf.Clamp(moveStep, -absOffset, absOffset);
float newX = currentX + moveStep; float newX = currentX + moveStep;
newX = Mathf.Clamp(newX, settings.ClampXMin, settings.ClampXMax); newX = Mathf.Clamp(newX, _settings.ClampXMin, _settings.ClampXMax);
UpdatePosition(newX); UpdatePosition(newX);
} }
// Handle tap impulse movement // Handle tap impulse movement
else if (tapImpulseStrength > 0) else if (_tapImpulseStrength > 0)
{ {
float currentX = transform.position.x; float currentX = transform.position.x;
float maxOffset = settings.MaxOffset; float maxOffset = _settings.MaxOffset;
float lerpSpeed = settings.LerpSpeed; float lerpSpeed = _settings.LerpSpeed;
// Calculate move distance based on impulse strength // Calculate move distance based on impulse strength
float moveDistance = maxOffset * tapImpulseStrength * Time.deltaTime * lerpSpeed; float moveDistance = maxOffset * _tapImpulseStrength * Time.deltaTime * lerpSpeed;
// Limit total movement from single tap // Limit total movement from single tap
moveDistance = Mathf.Min(moveDistance, settings.TapMaxDistance * tapImpulseStrength); moveDistance = Mathf.Min(moveDistance, _settings.TapMaxDistance * _tapImpulseStrength);
// Apply movement in tap direction // Apply movement in tap direction
float newX = currentX + (moveDistance * tapDirection); float newX = currentX + (moveDistance * _tapDirection);
newX = Mathf.Clamp(newX, settings.ClampXMin, settings.ClampXMax); newX = Mathf.Clamp(newX, _settings.ClampXMin, _settings.ClampXMax);
// Reduce impulse strength over time // Reduce impulse strength over time
tapImpulseStrength -= Time.deltaTime * settings.TapDecelerationRate; _tapImpulseStrength -= Time.deltaTime * _settings.TapDecelerationRate;
if (tapImpulseStrength < 0.01f) if (_tapImpulseStrength < 0.01f)
{ {
tapImpulseStrength = 0f; _tapImpulseStrength = 0f;
} }
UpdatePosition(newX); UpdatePosition(newX);
@@ -243,7 +243,7 @@ namespace Minigames.DivingForPictures.Player
/// </summary> /// </summary>
private void UpdatePosition(float newX) private void UpdatePosition(float newX)
{ {
float newY = originY; float newY = _originY;
// Add vertical offset from WobbleBehavior if present // Add vertical offset from WobbleBehavior if present
WobbleBehavior wobble = GetComponent<WobbleBehavior>(); WobbleBehavior wobble = GetComponent<WobbleBehavior>();
if (wobble != null) if (wobble != null)
@@ -258,7 +258,7 @@ namespace Minigames.DivingForPictures.Player
/// </summary> /// </summary>
public void UpdateOriginY(float newOriginY) public void UpdateOriginY(float newOriginY)
{ {
originY = newOriginY; _originY = newOriginY;
} }
/// <summary> /// <summary>
@@ -267,7 +267,7 @@ namespace Minigames.DivingForPictures.Player
/// </summary> /// </summary>
private void UpdateOriginYFromCurrentPosition() private void UpdateOriginYFromCurrentPosition()
{ {
originY = transform.position.y; _originY = transform.position.y;
} }
/// <summary> /// <summary>
@@ -276,24 +276,21 @@ namespace Minigames.DivingForPictures.Player
/// </summary> /// </summary>
private void UpdateOriginYFromAnchor() private void UpdateOriginYFromAnchor()
{ {
originY = edgeAnchor.transform.position.y; _originY = edgeAnchor.transform.position.y;
} }
#region IPausable Implementation #region IPausable Implementation
private bool isPaused = false;
/// <summary> /// <summary>
/// Pauses the player controller, blocking all input processing /// Pauses the player controller, blocking all input processing
/// </summary> /// </summary>
public void Pause() public void Pause()
{ {
if (isPaused) return; if (GameManager.Instance.IsPaused) return;
isPaused = true;
// If we're being paused, stop any active touch and tap impulse // If we're being paused, stop any active touch and tap impulse
isTouchActive = false; _isTouchActive = false;
tapImpulseStrength = 0f; _tapImpulseStrength = 0f;
Logging.Debug("[PlayerController] Paused"); Logging.Debug("[PlayerController] Paused");
} }
@@ -303,16 +300,9 @@ namespace Minigames.DivingForPictures.Player
/// </summary> /// </summary>
public void DoResume() public void DoResume()
{ {
if (!isPaused) return; if (!GameManager.Instance.IsPaused) return;
isPaused = false;
Logging.Debug("[PlayerController] Resumed"); Logging.Debug("[PlayerController] Resumed");
} }
/// <summary>
/// Returns whether the player controller is currently paused
/// </summary>
public bool IsPaused => isPaused;
#endregion #endregion
} }
} }

View File

@@ -1,5 +1,6 @@
using UnityEngine; using UnityEngine;
using AppleHills.Core.Settings; using AppleHills.Core.Settings;
using Core;
/// <summary> /// <summary>
/// Adds a wobble (rocking and vertical movement) effect to the object, based on speed and time. /// Adds a wobble (rocking and vertical movement) effect to the object, based on speed and time.

View File

@@ -1,10 +1,8 @@
using System; using System.Collections;
using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using UnityEngine; using UnityEngine;
using UnityEngine.Events; using UnityEngine.Events;
using UnityEngine.Serialization; using UnityEngine.Serialization;
using Pooling;
using AppleHills.Core.Settings; using AppleHills.Core.Settings;
using Utils; using Utils;
using AppleHills.Core.Interfaces; using AppleHills.Core.Interfaces;
@@ -113,12 +111,6 @@ namespace Minigames.DivingForPictures
} }
} }
// Pause state
private bool _isPaused = false;
// IPausable implementation
public bool IsPaused => _isPaused;
private void Awake() private void Awake()
{ {
_mainCamera = UnityEngine.Camera.main; _mainCamera = UnityEngine.Camera.main;
@@ -193,9 +185,7 @@ namespace Minigames.DivingForPictures
/// </summary> /// </summary>
public void Pause() public void Pause()
{ {
if (_isPaused) return; // Already paused if (GameManager.Instance.IsPaused) return; // Already paused
_isPaused = true;
// Stop all active coroutines but save their references // Stop all active coroutines but save their references
if (_movementCoroutine != null) if (_movementCoroutine != null)
@@ -230,9 +220,7 @@ namespace Minigames.DivingForPictures
/// </summary> /// </summary>
public void DoResume() public void DoResume()
{ {
if (!_isPaused) return; // Already running if (!GameManager.Instance.IsPaused) return; // Already running
_isPaused = false;
// Restart all necessary coroutines // Restart all necessary coroutines
StartMovementCoroutine(); StartMovementCoroutine();
@@ -500,7 +488,7 @@ namespace Minigames.DivingForPictures
/// </summary> /// </summary>
private void StartMovementCoroutine() private void StartMovementCoroutine()
{ {
if (_movementCoroutine == null && !_isPaused) if (_movementCoroutine == null && !GameManager.Instance.IsPaused)
{ {
_movementCoroutine = StartCoroutine(MoveActiveTilesRoutine()); _movementCoroutine = StartCoroutine(MoveActiveTilesRoutine());
} }
@@ -513,7 +501,7 @@ namespace Minigames.DivingForPictures
{ {
Logging.Debug($"[TrenchTileSpawner] Started movement coroutine with normalized speed: {_baseMoveSpeed:F3}"); Logging.Debug($"[TrenchTileSpawner] Started movement coroutine with normalized speed: {_baseMoveSpeed:F3}");
while (enabled && gameObject.activeInHierarchy && !_isPaused) while (enabled && gameObject.activeInHierarchy && !GameManager.Instance.IsPaused)
{ {
// Skip if no active tiles // Skip if no active tiles
if (_activeTiles.Count == 0) if (_activeTiles.Count == 0)
@@ -554,7 +542,7 @@ namespace Minigames.DivingForPictures
const float checkInterval = 1.0f; // Check once per second const float checkInterval = 1.0f; // Check once per second
Logging.Debug($"[TrenchTileSpawner] Started speed ramping coroutine with interval: {checkInterval}s"); Logging.Debug($"[TrenchTileSpawner] Started speed ramping coroutine with interval: {checkInterval}s");
while (enabled && gameObject.activeInHierarchy && !_isPaused) while (enabled && gameObject.activeInHierarchy && !GameManager.Instance.IsPaused)
{ {
// Increase the base move speed up to the maximum // Increase the base move speed up to the maximum
_baseMoveSpeed = Mathf.Min(_baseMoveSpeed + _settings.SpeedUpFactor, _settings.MaxNormalizedMoveSpeed); _baseMoveSpeed = Mathf.Min(_baseMoveSpeed + _settings.SpeedUpFactor, _settings.MaxNormalizedMoveSpeed);

View File

@@ -7,8 +7,6 @@ namespace Minigames.DivingForPictures.Utilities
{ {
[SerializeField] private WobbleBehavior wobbleReference; [SerializeField] private WobbleBehavior wobbleReference;
private bool isPaused = false;
private void Start() private void Start()
{ {
DivingGameManager.Instance.RegisterPausableComponent(this); DivingGameManager.Instance.RegisterPausableComponent(this);
@@ -17,15 +15,11 @@ namespace Minigames.DivingForPictures.Utilities
public void Pause() public void Pause()
{ {
wobbleReference.enabled = false; wobbleReference.enabled = false;
isPaused = true;
} }
public void DoResume() public void DoResume()
{ {
wobbleReference.enabled = true; wobbleReference.enabled = true;
isPaused = false;
} }
public bool IsPaused => isPaused;
} }
} }

View File

@@ -8,8 +8,6 @@ namespace Minigames.DivingForPictures.Utilities
[SerializeField] private RockFollower rockReference; [SerializeField] private RockFollower rockReference;
[SerializeField] private WobbleBehavior rockWobbleReference; [SerializeField] private WobbleBehavior rockWobbleReference;
private bool isPaused = false;
private void Start() private void Start()
{ {
DivingGameManager.Instance.RegisterPausableComponent(this); DivingGameManager.Instance.RegisterPausableComponent(this);
@@ -19,16 +17,12 @@ namespace Minigames.DivingForPictures.Utilities
{ {
rockReference.enabled = false; rockReference.enabled = false;
rockWobbleReference.enabled = false; rockWobbleReference.enabled = false;
isPaused = true;
} }
public void DoResume() public void DoResume()
{ {
rockReference.enabled = true; rockReference.enabled = true;
rockWobbleReference.enabled = true; rockWobbleReference.enabled = true;
isPaused = false;
} }
public bool IsPaused => isPaused;
} }
} }

View File

@@ -4,6 +4,7 @@ using Pathfinding;
using UnityEngine.SceneManagement; using UnityEngine.SceneManagement;
using Utils; using Utils;
using AppleHills.Core.Settings; using AppleHills.Core.Settings;
using Core;
/// <summary> /// <summary>
/// Controls the follower character, including following the player, handling pickups, and managing held items. /// Controls the follower character, including following the player, handling pickups, and managing held items.

View File

@@ -24,15 +24,6 @@ namespace UI
[SerializeField] private GameObject pauseButton; [SerializeField] private GameObject pauseButton;
[SerializeField] private CanvasGroup canvasGroup; [SerializeField] private CanvasGroup canvasGroup;
public event Action OnGamePaused;
public event Action OnGameResumed;
private bool _isPaused = false;
/// <summary>
/// Returns whether the game is currently paused
/// </summary>
public bool IsPaused => _isPaused;
private void Awake() private void Awake()
{ {
@@ -103,7 +94,7 @@ namespace UI
/// </summary> /// </summary>
public void ShowPauseMenu() public void ShowPauseMenu()
{ {
if (_isPaused) return; if (GameManager.Instance.IsPaused) return;
if (UIPageController.Instance != null) if (UIPageController.Instance != null)
{ {
UIPageController.Instance.PushPage(this); UIPageController.Instance.PushPage(this);
@@ -130,7 +121,7 @@ namespace UI
/// </summary> /// </summary>
public void HidePauseMenu(bool resetInput = true) public void HidePauseMenu(bool resetInput = true)
{ {
if (!_isPaused) if (!GameManager.Instance.IsPaused)
{ {
// Ensure UI is hidden if somehow active without state // Ensure UI is hidden if somehow active without state
if (pauseMenuPanel != null) pauseMenuPanel.SetActive(false); if (pauseMenuPanel != null) pauseMenuPanel.SetActive(false);
@@ -169,19 +160,17 @@ namespace UI
private void BeginPauseSideEffects() private void BeginPauseSideEffects()
{ {
_isPaused = true;
if (pauseButton != null) pauseButton.SetActive(false); if (pauseButton != null) pauseButton.SetActive(false);
InputManager.Instance.SetInputMode(InputMode.UI); InputManager.Instance.SetInputMode(InputMode.UI);
OnGamePaused?.Invoke(); GameManager.Instance.RequestGamePause();
Logging.Debug("[PauseMenu] Game Paused"); Logging.Debug("[PauseMenu] Game Paused");
} }
private void EndPauseSideEffects(bool invokeEvent) private void EndPauseSideEffects(bool invokeEvent)
{ {
_isPaused = false;
if (pauseButton != null) pauseButton.SetActive(true); if (pauseButton != null) pauseButton.SetActive(true);
InputManager.Instance.SetInputMode(InputMode.GameAndUI); InputManager.Instance.SetInputMode(InputMode.GameAndUI);
if (invokeEvent) OnGameResumed?.Invoke(); GameManager.Instance.RequestGameResume();
Logging.Debug("[PauseMenu] Game Resumed"); Logging.Debug("[PauseMenu] Game Resumed");
} }