using UnityEngine; /// /// Singleton manager for global game state and settings. Provides accessors for various gameplay parameters. /// public class GameManager : MonoBehaviour { private static GameManager _instance; private static bool _isQuitting = false; /// /// Singleton instance of the GameManager. /// public static GameManager Instance { get { if (_instance == null && Application.isPlaying && !_isQuitting) { _instance = FindAnyObjectByType(); if (_instance == null) { var go = new GameObject("GameManager"); _instance = go.AddComponent(); // DontDestroyOnLoad(go); } } return _instance; } } [Header("Game Settings")] public GameSettings gameSettings; void Awake() { _instance = this; // DontDestroyOnLoad(gameObject); } void OnApplicationQuit() { _isQuitting = true; } // Accessors for game settings public float PlayerStopDistance => gameSettings != null ? gameSettings.playerStopDistance : 1.0f; public float FollowerPickupDelay => gameSettings != null ? gameSettings.followerPickupDelay : 0.2f; public float FollowDistance => gameSettings != null ? gameSettings.followDistance : 1.5f; public float ManualMoveSmooth => gameSettings != null ? gameSettings.manualMoveSmooth : 8f; public float ThresholdFar => gameSettings != null ? gameSettings.thresholdFar : 2.5f; public float ThresholdNear => gameSettings != null ? gameSettings.thresholdNear : 0.5f; public float StopThreshold => gameSettings != null ? gameSettings.stopThreshold : 0.5f; public float MoveSpeed => gameSettings != null ? gameSettings.moveSpeed : 5f; public float StopDistance => gameSettings != null ? gameSettings.stopDistance : 0.1f; public bool UseRigidbody => gameSettings != null ? gameSettings.useRigidbody : true; public float FollowUpdateInterval => gameSettings != null ? gameSettings.followUpdateInterval : 0.1f; public float FollowerSpeedMultiplier => gameSettings != null ? gameSettings.followerSpeedMultiplier : 1.2f; public float HeldIconDisplayHeight => gameSettings != null ? gameSettings.heldIconDisplayHeight : 2.0f; public GameObject BasePickupPrefab => gameSettings != null ? gameSettings.basePickupPrefab : null; public LayerMask InteractableLayerMask => gameSettings != null ? gameSettings.interactableLayerMask : -1; public float PlayerStopDistanceDirectInteraction => gameSettings != null ? gameSettings.playerStopDistanceDirectInteraction : 2.0f; /// /// Returns the combination rule for two items, if any. /// public GameSettings.CombinationRule GetCombinationRule(PickupItemData item1, PickupItemData item2) { if (gameSettings == null || gameSettings.combinationRules == null) return null; foreach (var rule in gameSettings.combinationRules) { if ((rule.itemA == item1 && rule.itemB == item2) || (rule.itemA == item2 && rule.itemB == item1)) { return rule; } } return null; } /// /// Returns the slot item config for a given slot item. /// public GameSettings.SlotItemConfig GetSlotItemConfig(PickupItemData slotItem) { if (gameSettings == null || gameSettings.slotItemConfigs == null || slotItem == null) return null; foreach (var config in gameSettings.slotItemConfigs) { if (config.slotItem == slotItem) return config; } return null; } // Add more accessors as needed public float EndlessDescenderLerpSpeed => gameSettings != null ? gameSettings.endlessDescenderLerpSpeed : 12f; public float EndlessDescenderMaxOffset => gameSettings != null ? gameSettings.endlessDescenderMaxOffset : 3f; public float EndlessDescenderClampXMin => gameSettings != null ? gameSettings.endlessDescenderClampXMin : -5f; public float EndlessDescenderClampXMax => gameSettings != null ? gameSettings.endlessDescenderClampXMax : 5f; public float EndlessDescenderSpeedExponent => gameSettings != null ? gameSettings.endlessDescenderSpeedExponent : 2.5f; public GameSettings.HoldMovementMode DefaultHoldMovementMode => gameSettings != null ? gameSettings.defaultHoldMovementMode : GameSettings.HoldMovementMode.Pathfinding; public GameObject LevelSwitchMenuPrefab => gameSettings != null ? gameSettings.levelSwitchMenuPrefab : null; }