Remove dependencies on legacy variables in GameManager.Instance

This commit is contained in:
Michal Pikulski
2025-10-07 10:44:26 +02:00
parent c46036dce6
commit f845673eca
9 changed files with 113 additions and 89 deletions

View File

@@ -160,71 +160,9 @@ public class GameManager : MonoBehaviour
return DeveloperSettingsProvider.Instance?.GetSettings<T>(); return DeveloperSettingsProvider.Instance?.GetSettings<T>();
} }
// PLAYER & FOLLOWER SETTINGS // LEFTOVER LEGACY 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 PlayerStopDistance => GetSettings<IInteractionSettings>()?.PlayerStopDistance ?? 6.0f;
public float PlayerStopDistanceDirectInteraction => GetSettings<IInteractionSettings>()?.PlayerStopDistanceDirectInteraction ?? 2.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 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;
}
} }

View File

@@ -53,5 +53,38 @@ namespace AppleHills.Core.Settings
followerPickupDelay = Mathf.Max(0f, followerPickupDelay); followerPickupDelay = Mathf.Max(0f, followerPickupDelay);
defaultPuzzlePromptRange = Mathf.Max(0.1f, defaultPuzzlePromptRange); defaultPuzzlePromptRange = Mathf.Max(0.1f, defaultPuzzlePromptRange);
} }
/// <summary>
/// Returns the combination rule for two items, if any.
/// </summary>
public CombinationRule GetCombinationRule(PickupItemData item1, PickupItemData item2)
{
if (combinationRules == null) return null;
foreach (var rule in 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)
{
if (slotItemConfigs == null || slotItem == null) return null;
foreach (var config in slotItemConfigs)
{
if (PickupItemData.AreEquivalent(slotItem, config.slotItem))
return config;
}
return null;
}
} }
} }

View File

@@ -43,6 +43,10 @@ namespace AppleHills.Core.Settings
// Puzzle settings // Puzzle settings
GameObject DefaultPuzzleIndicatorPrefab { get; } GameObject DefaultPuzzleIndicatorPrefab { get; }
float DefaultPuzzlePromptRange { get; } float DefaultPuzzlePromptRange { get; }
// Methods to query item configurations
CombinationRule GetCombinationRule(PickupItemData item1, PickupItemData item2);
SlotItemConfig GetSlotItemConfig(PickupItemData slotItem);
} }
/// <summary> /// <summary>

View File

@@ -3,6 +3,7 @@ using UnityEngine;
using UnityEngine.EventSystems; using UnityEngine.EventSystems;
using UnityEngine.InputSystem; using UnityEngine.InputSystem;
using UnityEngine.SceneManagement; using UnityEngine.SceneManagement;
using AppleHills.Core.Settings; // Added for IInteractionSettings
namespace Input namespace Input
{ {
@@ -44,6 +45,9 @@ namespace Input
} }
} }
// Settings reference
private IInteractionSettings _interactionSettings;
private PlayerInput playerInput; private PlayerInput playerInput;
private InputAction tapMoveAction; private InputAction tapMoveAction;
private InputAction holdMoveAction; private InputAction holdMoveAction;
@@ -55,6 +59,10 @@ namespace Input
{ {
_instance = this; _instance = this;
// DontDestroyOnLoad(gameObject); // DontDestroyOnLoad(gameObject);
// Initialize settings reference
_interactionSettings = GameManager.GetSettingsObject<IInteractionSettings>();
playerInput = GetComponent<PlayerInput>(); playerInput = GetComponent<PlayerInput>();
if (playerInput == null) if (playerInput == null)
{ {
@@ -217,7 +225,7 @@ namespace Input
/// </summary> /// </summary>
private bool TryDelegateToInteractable(Vector2 worldPos) private bool TryDelegateToInteractable(Vector2 worldPos)
{ {
LayerMask mask = GameManager.Instance != null ? GameManager.Instance.InteractableLayerMask : -1; LayerMask mask = _interactionSettings != null ? _interactionSettings.InteractableLayerMask : -1;
Collider2D hit = Physics2D.OverlapPoint(worldPos, mask); Collider2D hit = Physics2D.OverlapPoint(worldPos, mask);
if (hit != null) if (hit != null)
{ {

View File

@@ -3,6 +3,7 @@ using UnityEngine;
using UnityEngine.Events; using UnityEngine.Events;
using System; // for Action<T> using System; // for Action<T>
using Core; // register with ItemManager using Core; // register with ItemManager
using AppleHills.Core.Settings; // Added for IInteractionSettings
namespace Interactions namespace Interactions
{ {
@@ -24,6 +25,10 @@ namespace Interactions
// Tracks the current state of the slotted item // Tracks the current state of the slotted item
private ItemSlotState _currentState = ItemSlotState.None; private ItemSlotState _currentState = ItemSlotState.None;
// Settings reference
private IInteractionSettings _interactionSettings;
private IPlayerFollowerSettings _playerFollowerSettings;
/// <summary> /// <summary>
/// Read-only access to the current slotted item state. /// Read-only access to the current slotted item state.
/// </summary> /// </summary>
@@ -64,13 +69,22 @@ namespace Interactions
} }
} }
public override void Awake()
{
base.Awake();
// Initialize settings references
_interactionSettings = GameManager.GetSettingsObject<IInteractionSettings>();
_playerFollowerSettings = GameManager.GetSettingsObject<IPlayerFollowerSettings>();
}
protected override void OnCharacterArrived() protected override void OnCharacterArrived()
{ {
Debug.Log("[ItemSlot] OnCharacterArrived"); Debug.Log("[ItemSlot] OnCharacterArrived");
var heldItemData = FollowerController.CurrentlyHeldItemData; var heldItemData = FollowerController.CurrentlyHeldItemData;
var heldItemObj = FollowerController.GetHeldPickupObject(); var heldItemObj = FollowerController.GetHeldPickupObject();
var config = GameManager.Instance.GetSlotItemConfig(itemData); var config = _interactionSettings?.GetSlotItemConfig(itemData);
var forbidden = config?.forbiddenItems ?? new List<PickupItemData>(); var forbidden = config?.forbiddenItems ?? new List<PickupItemData>();
// Held item, slot empty -> try to slot item // Held item, slot empty -> try to slot item
@@ -120,7 +134,7 @@ namespace Interactions
{ {
slottedItemRenderer.sprite = _currentlySlottedItemData.mapSprite; slottedItemRenderer.sprite = _currentlySlottedItemData.mapSprite;
// Scale sprite to desired height, preserve aspect ratio, compensate for parent scale // Scale sprite to desired height, preserve aspect ratio, compensate for parent scale
float desiredHeight = GameManager.Instance.HeldIconDisplayHeight; float desiredHeight = _playerFollowerSettings?.HeldIconDisplayHeight ?? 2.0f;
var sprite = _currentlySlottedItemData.mapSprite; var sprite = _currentlySlottedItemData.mapSprite;
float spriteHeight = sprite.bounds.size.y; float spriteHeight = sprite.bounds.size.y;
float spriteWidth = sprite.bounds.size.x; float spriteWidth = sprite.bounds.size.x;
@@ -175,7 +189,7 @@ namespace Interactions
// Once an item is slotted, we know it is not forbidden, so we can skip that check, but now check if it was // Once an item is slotted, we know it is not forbidden, so we can skip that check, but now check if it was
// the correct item we're looking for // the correct item we're looking for
var config = GameManager.Instance.GetSlotItemConfig(itemData); var config = _interactionSettings?.GetSlotItemConfig(itemData);
var allowed = config?.allowedItems ?? new List<PickupItemData>(); var allowed = config?.allowedItems ?? new List<PickupItemData>();
if (itemToSlotData != null && PickupItemData.ListContainsEquivalent(allowed, itemToSlotData)) if (itemToSlotData != null && PickupItemData.ListContainsEquivalent(allowed, itemToSlotData))
{ {

View File

@@ -26,7 +26,7 @@ namespace Interactions
/// <summary> /// <summary>
/// Unity Awake callback. Sets up icon, interactable, and event handlers. /// Unity Awake callback. Sets up icon, interactable, and event handlers.
/// </summary> /// </summary>
void Awake() public virtual void Awake()
{ {
if (iconRenderer == null) if (iconRenderer == null)
iconRenderer = GetComponent<SpriteRenderer>(); iconRenderer = GetComponent<SpriteRenderer>();

View File

@@ -2,6 +2,7 @@
using Input; using Input;
using Interactions; using Interactions;
using UnityEngine; using UnityEngine;
using AppleHills.Core.Settings; // Added for IInteractionSettings
/// <summary> /// <summary>
/// Handles level switching when interacted with. Applies switch data and triggers scene transitions. /// Handles level switching when interacted with. Applies switch data and triggers scene transitions.
@@ -15,6 +16,9 @@ public class LevelSwitch : MonoBehaviour
private SpriteRenderer _iconRenderer; private SpriteRenderer _iconRenderer;
private Interactable _interactable; private Interactable _interactable;
// Settings reference
private IInteractionSettings _interactionSettings;
private bool _isActive = true; private bool _isActive = true;
/// <summary> /// <summary>
@@ -30,6 +34,10 @@ public class LevelSwitch : MonoBehaviour
{ {
_interactable.characterArrived.AddListener(OnCharacterArrived); _interactable.characterArrived.AddListener(OnCharacterArrived);
} }
// Initialize settings reference
_interactionSettings = GameManager.GetSettingsObject<IInteractionSettings>();
ApplySwitchData(); ApplySwitchData();
} }
@@ -78,10 +86,10 @@ public class LevelSwitch : MonoBehaviour
if (switchData == null || string.IsNullOrEmpty(switchData.targetLevelSceneName) || !_isActive) if (switchData == null || string.IsNullOrEmpty(switchData.targetLevelSceneName) || !_isActive)
return; return;
var menuPrefab = GameManager.Instance.LevelSwitchMenuPrefab; var menuPrefab = _interactionSettings?.LevelSwitchMenuPrefab;
if (menuPrefab == null) if (menuPrefab == null)
{ {
Debug.LogError("LevelSwitchMenu prefab not assigned in GameSettings!"); Debug.LogError("LevelSwitchMenu prefab not assigned in InteractionSettings!");
return; return;
} }
// Spawn the menu overlay (assume Canvas parent is handled in prefab setup) // Spawn the menu overlay (assume Canvas parent is handled in prefab setup)

View File

@@ -3,6 +3,7 @@ using UnityEngine;
using Pathfinding; using Pathfinding;
using UnityEngine.SceneManagement; using UnityEngine.SceneManagement;
using Utils; using Utils;
using AppleHills.Core.Settings;
/// <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.
@@ -20,6 +21,10 @@ public class FollowerController: MonoBehaviour
/// </summary> /// </summary>
public float manualMoveSmooth = 8f; public float manualMoveSmooth = 8f;
// Settings reference
private IPlayerFollowerSettings _settings;
private IInteractionSettings _interactionSettings;
private GameObject _playerRef; private GameObject _playerRef;
private Transform _playerTransform; private Transform _playerTransform;
private AIPath _playerAIPath; private AIPath _playerAIPath;
@@ -80,6 +85,10 @@ public class FollowerController: MonoBehaviour
_animator = GetComponentInChildren<Animator>(); // fallback _animator = GetComponentInChildren<Animator>(); // fallback
_spriteRenderer = GetComponentInChildren<SpriteRenderer>(); _spriteRenderer = GetComponentInChildren<SpriteRenderer>();
} }
// Initialize settings references
_settings = GameManager.GetSettingsObject<IPlayerFollowerSettings>();
_interactionSettings = GameManager.GetSettingsObject<IInteractionSettings>();
} }
void OnEnable() void OnEnable()
@@ -108,7 +117,7 @@ public class FollowerController: MonoBehaviour
} }
_timer += Time.deltaTime; _timer += Time.deltaTime;
if (_timer >= GameManager.Instance.FollowUpdateInterval) if (_timer >= _settings.FollowUpdateInterval)
{ {
_timer = 0f; _timer = 0f;
UpdateFollowTarget(); UpdateFollowTarget();
@@ -120,24 +129,24 @@ public class FollowerController: MonoBehaviour
Vector2 target2D = new Vector2(_targetPoint.x, _targetPoint.y); Vector2 target2D = new Vector2(_targetPoint.x, _targetPoint.y);
float dist = Vector2.Distance(current2D, target2D); float dist = Vector2.Distance(current2D, target2D);
float minSpeed = _followerMaxSpeed * 0.3f; float minSpeed = _followerMaxSpeed * 0.3f;
float lerpFactor = GameManager.Instance.ManualMoveSmooth * Time.deltaTime; float lerpFactor = _settings.ManualMoveSmooth * Time.deltaTime;
float targetSpeed = 0f; float targetSpeed = 0f;
if (dist > GameManager.Instance.StopThreshold) if (dist > _settings.StopThreshold)
{ {
if (dist > GameManager.Instance.ThresholdFar) if (dist > _settings.ThresholdFar)
{ {
targetSpeed = _followerMaxSpeed; targetSpeed = _followerMaxSpeed;
} }
else if (dist > GameManager.Instance.ThresholdNear && dist <= GameManager.Instance.ThresholdFar) else if (dist > _settings.ThresholdNear && dist <= _settings.ThresholdFar)
{ {
targetSpeed = _followerMaxSpeed; targetSpeed = _followerMaxSpeed;
} }
else if (dist > GameManager.Instance.StopThreshold && dist <= GameManager.Instance.ThresholdNear) else if (dist > _settings.StopThreshold && dist <= _settings.ThresholdNear)
{ {
targetSpeed = minSpeed; targetSpeed = minSpeed;
} }
_currentSpeed = Mathf.Lerp(_currentSpeed, targetSpeed, lerpFactor); _currentSpeed = Mathf.Lerp(_currentSpeed, targetSpeed, lerpFactor);
if (dist > GameManager.Instance.StopThreshold && dist <= GameManager.Instance.ThresholdNear) if (dist > _settings.StopThreshold && dist <= _settings.ThresholdNear)
{ {
_currentSpeed = Mathf.Max(_currentSpeed, minSpeed); _currentSpeed = Mathf.Max(_currentSpeed, minSpeed);
} }
@@ -215,7 +224,7 @@ public class FollowerController: MonoBehaviour
{ {
_playerMaxSpeed = _playerAIPath.maxSpeed; _playerMaxSpeed = _playerAIPath.maxSpeed;
_defaultFollowerMaxSpeed = _playerMaxSpeed; _defaultFollowerMaxSpeed = _playerMaxSpeed;
_followerMaxSpeed = _playerMaxSpeed * GameManager.Instance.FollowerSpeedMultiplier; _followerMaxSpeed = _playerMaxSpeed * _settings.FollowerSpeedMultiplier;
} }
} }
else else
@@ -258,8 +267,8 @@ public class FollowerController: MonoBehaviour
{ {
moveDir = _lastMoveDir; moveDir = _lastMoveDir;
} }
// Use GameSettings for followDistance // Use settings for followDistance
_targetPoint = playerPos - moveDir * GameManager.Instance.FollowDistance; _targetPoint = playerPos - moveDir * _settings.FollowDistance;
_targetPoint.z = 0; _targetPoint.z = 0;
if (_aiPath != null) if (_aiPath != null)
{ {
@@ -310,14 +319,14 @@ public class FollowerController: MonoBehaviour
_aiPath.destination = new Vector3(itemPosition.x, itemPosition.y, 0); _aiPath.destination = new Vector3(itemPosition.x, itemPosition.y, 0);
} }
// Wait until follower reaches item (2D distance) // Wait until follower reaches item (2D distance)
while (Vector2.Distance(new Vector2(transform.position.x, transform.position.y), new Vector2(itemPosition.x, itemPosition.y)) > GameManager.Instance.StopThreshold) while (Vector2.Distance(new Vector2(transform.position.x, transform.position.y), new Vector2(itemPosition.x, itemPosition.y)) > _settings.StopThreshold)
{ {
yield return null; yield return null;
} }
OnPickupArrived?.Invoke(); OnPickupArrived?.Invoke();
// Wait briefly, then return to player // Wait briefly, then return to player
yield return new WaitForSeconds(0.2f); yield return new WaitForSeconds(_interactionSettings.FollowerPickupDelay);
if (_aiPath != null && playerTransform != null) if (_aiPath != null && playerTransform != null)
{ {
_aiPath.maxSpeed = _followerMaxSpeed; _aiPath.maxSpeed = _followerMaxSpeed;
@@ -325,7 +334,7 @@ public class FollowerController: MonoBehaviour
} }
_isReturningToPlayer = true; _isReturningToPlayer = true;
// Wait until follower returns to player (2D distance) // Wait until follower returns to player (2D distance)
while (playerTransform != null && Vector2.Distance(new Vector2(transform.position.x, transform.position.y), new Vector2(playerTransform.position.x, playerTransform.position.y)) > GameManager.Instance.StopThreshold) while (playerTransform != null && Vector2.Distance(new Vector2(transform.position.x, transform.position.y), new Vector2(playerTransform.position.x, playerTransform.position.y)) > _settings.StopThreshold)
{ {
yield return null; yield return null;
} }
@@ -375,11 +384,14 @@ public class FollowerController: MonoBehaviour
{ {
return CombinationResult.NotApplicable; return CombinationResult.NotApplicable;
} }
var rule = GameManager.Instance.GetCombinationRule(pickupA.itemData, pickupB.itemData);
// Use the InteractionSettings directly instead of GameManager
CombinationRule matchingRule = _interactionSettings.GetCombinationRule(pickupA.itemData, pickupB.itemData);
Vector3 spawnPos = pickupA.gameObject.transform.position; Vector3 spawnPos = pickupA.gameObject.transform.position;
if (rule != null && rule.resultPrefab != null) if (matchingRule != null && matchingRule.resultPrefab != null)
{ {
newItem = Instantiate(rule.resultPrefab, spawnPos, Quaternion.identity); newItem = Instantiate(matchingRule.resultPrefab, spawnPos, Quaternion.identity);
PickupItemData itemData = newItem.GetComponent<Pickup>().itemData; PickupItemData itemData = newItem.GetComponent<Pickup>().itemData;
Destroy(pickupA.gameObject); Destroy(pickupA.gameObject);
Destroy(pickupB.gameObject); Destroy(pickupB.gameObject);

View File

@@ -4,6 +4,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using UnityEngine; using UnityEngine;
using UnityEngine.SceneManagement; using UnityEngine.SceneManagement;
using AppleHills.Core.Settings; // Added for IInteractionSettings
namespace PuzzleS namespace PuzzleS
{ {
@@ -21,6 +22,9 @@ namespace PuzzleS
private Transform _playerTransform; private Transform _playerTransform;
private Coroutine _proximityCheckCoroutine; private Coroutine _proximityCheckCoroutine;
// Settings reference
private IInteractionSettings _interactionSettings;
/// <summary> /// <summary>
/// Singleton instance of the PuzzleManager. /// Singleton instance of the PuzzleManager.
/// </summary> /// </summary>
@@ -58,6 +62,9 @@ namespace PuzzleS
_instance = this; _instance = this;
// DontDestroyOnLoad(gameObject); // DontDestroyOnLoad(gameObject);
SceneManager.sceneLoaded += OnSceneLoaded; SceneManager.sceneLoaded += OnSceneLoaded;
// Initialize settings reference
_interactionSettings = GameManager.GetSettingsObject<IInteractionSettings>();
} }
void Start() void Start()
@@ -123,8 +130,8 @@ namespace PuzzleS
{ {
if (_playerTransform != null) if (_playerTransform != null)
{ {
// Get the proximity threshold from settings (half of the prompt range) // Get the proximity threshold from settings directly using our settings reference
float proximityThreshold = GameManager.Instance.DefaultPuzzlePromptRange; float proximityThreshold = _interactionSettings?.DefaultPuzzlePromptRange ?? 3.0f;
// Check distance to each step behavior // Check distance to each step behavior
foreach (var kvp in _stepBehaviours) foreach (var kvp in _stepBehaviours)