Files
AppleHillsProduction/Assets/Scripts/Core/GameManager.cs
Michal Pikulski dac119fd7b First steps
2025-10-02 07:17:07 +02:00

231 lines
8.8 KiB
C#

using UnityEngine;
using AppleHills.Core.Settings;
using System;
/// <summary>
/// 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>
/// Singleton instance of the GameManager.
/// </summary>
public static GameManager Instance
{
get
{
if (_instance == null && Application.isPlaying && !_isQuitting)
{
_instance = FindAnyObjectByType<GameManager>();
if (_instance == null)
{
var go = new GameObject("GameManager");
_instance = go.AddComponent<GameManager>();
// 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;
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 InitializeSettings()
{
Debug.Log("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);
Debug.Log("PlayerFollowerSettings registered successfully");
}
else
{
Debug.LogError("Failed to load PlayerFollowerSettings");
}
if (interactionSettings != null)
{
ServiceLocator.Register<IInteractionSettings>(interactionSettings);
Debug.Log("InteractionSettings registered successfully");
}
else
{
Debug.LogError("Failed to load InteractionSettings");
}
if (minigameSettings != null)
{
ServiceLocator.Register<IDivingMinigameSettings>(minigameSettings);
Debug.Log("MinigameSettings registered successfully");
}
else
{
Debug.LogError("Failed to load MinigameSettings");
}
// Log success
_settingsLoaded = playerSettings != null && interactionSettings != null && minigameSettings != null;
if (_settingsLoaded)
{
Debug.Log("All settings loaded and registered with ServiceLocator");
}
else
{
Debug.LogWarning("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()
{
Debug.Log("Starting developer settings initialization...");
// Load developer settings
var divingDevSettings = DeveloperSettingsProvider.Instance.GetSettings<DivingDeveloperSettings>();
_developerSettingsLoaded = divingDevSettings != null;
if (_developerSettingsLoaded)
{
Debug.Log("All developer settings loaded successfully");
}
else
{
Debug.LogWarning("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>();
}
// PLAYER & FOLLOWER SETTINGS
// Player settings
public float MoveSpeed => GetSettings<IPlayerFollowerSettings>()?.MoveSpeed ?? 5f;
public float StopDistance => GetSettings<IPlayerFollowerSettings>()?.StopDistance ?? 0.1f;
public bool UseRigidbody => GetSettings<IPlayerFollowerSettings>()?.UseRigidbody ?? true;
public HoldMovementMode DefaultHoldMovementMode =>
GetSettings<IPlayerFollowerSettings>()?.DefaultHoldMovementMode ?? HoldMovementMode.Pathfinding;
// Follower settings
public float FollowDistance => GetSettings<IPlayerFollowerSettings>()?.FollowDistance ?? 1.5f;
public float ManualMoveSmooth => GetSettings<IPlayerFollowerSettings>()?.ManualMoveSmooth ?? 8f;
public float ThresholdFar => GetSettings<IPlayerFollowerSettings>()?.ThresholdFar ?? 2.5f;
public float ThresholdNear => GetSettings<IPlayerFollowerSettings>()?.ThresholdNear ?? 0.5f;
public float StopThreshold => GetSettings<IPlayerFollowerSettings>()?.StopThreshold ?? 0.1f;
public float FollowUpdateInterval => GetSettings<IPlayerFollowerSettings>()?.FollowUpdateInterval ?? 0.1f;
public float FollowerSpeedMultiplier => GetSettings<IPlayerFollowerSettings>()?.FollowerSpeedMultiplier ?? 1.2f;
public float HeldIconDisplayHeight => GetSettings<IPlayerFollowerSettings>()?.HeldIconDisplayHeight ?? 2.0f;
// INTERACTION SETTINGS
public float PlayerStopDistance => GetSettings<IInteractionSettings>()?.PlayerStopDistance ?? 6.0f;
public float PlayerStopDistanceDirectInteraction => GetSettings<IInteractionSettings>()?.PlayerStopDistanceDirectInteraction ?? 2.0f;
public float FollowerPickupDelay => GetSettings<IInteractionSettings>()?.FollowerPickupDelay ?? 0.2f;
public LayerMask InteractableLayerMask => GetSettings<IInteractionSettings>()?.InteractableLayerMask ?? -1;
public GameObject BasePickupPrefab => GetSettings<IInteractionSettings>()?.BasePickupPrefab;
public GameObject LevelSwitchMenuPrefab => GetSettings<IInteractionSettings>()?.LevelSwitchMenuPrefab;
// PUZZLE SETTINGS
public float DefaultPuzzlePromptRange => GetSettings<IInteractionSettings>()?.DefaultPuzzlePromptRange ?? 3.0f;
public GameObject DefaultPuzzleIndicatorPrefab => GetSettings<IInteractionSettings>()?.DefaultPuzzleIndicatorPrefab;
/// <summary>
/// Returns the combination rule for two items, if any.
/// </summary>
public CombinationRule GetCombinationRule(PickupItemData item1, PickupItemData item2)
{
var settings = GetSettings<IInteractionSettings>();
if (settings == null || settings.CombinationRules == null) return null;
foreach (var rule in settings.CombinationRules)
{
if ((PickupItemData.AreEquivalent(rule.itemA, item1) && PickupItemData.AreEquivalent(rule.itemB, item2)) ||
(PickupItemData.AreEquivalent(rule.itemA, item2) && PickupItemData.AreEquivalent(rule.itemB, item1)))
{
return rule;
}
}
return null;
}
/// <summary>
/// Returns the slot item config for a given slot item.
/// </summary>
public SlotItemConfig GetSlotItemConfig(PickupItemData slotItem)
{
var settings = GetSettings<IInteractionSettings>();
if (settings == null || settings.SlotItemConfigs == null || slotItem == null) return null;
foreach (var config in settings.SlotItemConfigs)
{
if (PickupItemData.AreEquivalent(slotItem, config.slotItem))
return config;
}
return null;
}
}