Migrate settings to a more manageable structure and implement Service Locator pattern for runtime Addressables retrieval
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
using UnityEngine;
|
||||
using AppleHills.Core.Settings;
|
||||
using System.Collections;
|
||||
|
||||
/// <summary>
|
||||
/// Singleton manager for global game state and settings. Provides accessors for various gameplay parameters.
|
||||
@@ -29,53 +31,115 @@ public class GameManager : MonoBehaviour
|
||||
}
|
||||
}
|
||||
|
||||
[Header("Game Settings")]
|
||||
public GameSettings gameSettings;
|
||||
[Header("Legacy Game Settings (Deprecated)")]
|
||||
[Tooltip("This is only used for migration to the new settings system")]
|
||||
public GameSettings legacyGameSettings;
|
||||
|
||||
[Header("Settings Status")]
|
||||
[SerializeField] private bool _settingsLoaded = false;
|
||||
|
||||
void Awake()
|
||||
{
|
||||
_instance = this;
|
||||
if (gameSettings == null)
|
||||
{
|
||||
gameSettings = Resources.Load<GameSettings>("DefaultSettings");
|
||||
if (gameSettings == null)
|
||||
{
|
||||
Debug.LogError("GameSettings asset not found in Resources!");
|
||||
}
|
||||
}
|
||||
|
||||
// Create settings provider if it doesn't exist
|
||||
SettingsProvider.Instance.gameObject.name = "Settings Provider";
|
||||
|
||||
// Load all settings
|
||||
StartCoroutine(InitializeSettings());
|
||||
|
||||
// DontDestroyOnLoad(gameObject);
|
||||
}
|
||||
|
||||
private IEnumerator InitializeSettings()
|
||||
{
|
||||
// Initialize the settings provider
|
||||
var initComplete = false;
|
||||
SettingsProvider.Instance.PreloadAllSettings(() => initComplete = true);
|
||||
|
||||
// Wait for settings to be loaded
|
||||
while (!initComplete)
|
||||
{
|
||||
yield return null;
|
||||
}
|
||||
|
||||
// Register settings with service locator
|
||||
ServiceLocator.Register<IPlayerFollowerSettings>(
|
||||
SettingsProvider.Instance.GetSettings<PlayerFollowerSettings>());
|
||||
|
||||
ServiceLocator.Register<IInteractionSettings>(
|
||||
SettingsProvider.Instance.GetSettings<InteractionSettings>());
|
||||
|
||||
ServiceLocator.Register<IMinigameSettings>(
|
||||
SettingsProvider.Instance.GetSettings<MinigameSettings>());
|
||||
|
||||
// Log success
|
||||
Debug.Log("All settings loaded and registered with ServiceLocator");
|
||||
_settingsLoaded = true;
|
||||
|
||||
// Migrate settings if needed
|
||||
if (legacyGameSettings != null)
|
||||
{
|
||||
MigrateFromLegacySettings();
|
||||
}
|
||||
}
|
||||
|
||||
private void MigrateFromLegacySettings()
|
||||
{
|
||||
// This method can be used to copy settings from the old GameSettings to the new system
|
||||
// Implement if needed for your production environment
|
||||
Debug.Log("Legacy settings migration available but not implemented.");
|
||||
}
|
||||
|
||||
void OnApplicationQuit()
|
||||
{
|
||||
_isQuitting = true;
|
||||
ServiceLocator.Clear();
|
||||
}
|
||||
|
||||
// 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;
|
||||
// Helper method to get settings
|
||||
private T GetSettings<T>() where T : class
|
||||
{
|
||||
return ServiceLocator.Get<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 GameSettings.HoldMovementMode DefaultHoldMovementMode =>
|
||||
GetSettings<IPlayerFollowerSettings>()?.DefaultHoldMovementMode ?? GameSettings.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;
|
||||
|
||||
/// <summary>
|
||||
/// Returns the combination rule for two items, if any.
|
||||
/// </summary>
|
||||
public GameSettings.CombinationRule GetCombinationRule(PickupItemData item1, PickupItemData item2)
|
||||
{
|
||||
if (gameSettings == null || gameSettings.combinationRules == null) return null;
|
||||
foreach (var rule in gameSettings.combinationRules)
|
||||
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)))
|
||||
@@ -91,20 +155,23 @@ public class GameManager : MonoBehaviour
|
||||
/// </summary>
|
||||
public GameSettings.SlotItemConfig GetSlotItemConfig(PickupItemData slotItem)
|
||||
{
|
||||
if (gameSettings == null || gameSettings.slotItemConfigs == null || slotItem == null) return null;
|
||||
foreach (var config in gameSettings.slotItemConfigs)
|
||||
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;
|
||||
}
|
||||
// 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;
|
||||
|
||||
// MINIGAME SETTINGS
|
||||
|
||||
// Endless Descender settings
|
||||
public float EndlessDescenderLerpSpeed => GetSettings<IMinigameSettings>()?.EndlessDescenderLerpSpeed ?? 12f;
|
||||
public float EndlessDescenderMaxOffset => GetSettings<IMinigameSettings>()?.EndlessDescenderMaxOffset ?? 3f;
|
||||
public float EndlessDescenderClampXMin => GetSettings<IMinigameSettings>()?.EndlessDescenderClampXMin ?? -3.5f;
|
||||
public float EndlessDescenderClampXMax => GetSettings<IMinigameSettings>()?.EndlessDescenderClampXMax ?? 3.5f;
|
||||
public float EndlessDescenderSpeedExponent => GetSettings<IMinigameSettings>()?.EndlessDescenderSpeedExponent ?? 2.5f;
|
||||
}
|
||||
|
||||
3
Assets/Scripts/Core/Settings.meta
Normal file
3
Assets/Scripts/Core/Settings.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e380783135324fcd925048783e01d691
|
||||
timeCreated: 1758619858
|
||||
16
Assets/Scripts/Core/Settings/BaseSettings.cs
Normal file
16
Assets/Scripts/Core/Settings/BaseSettings.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace AppleHills.Core.Settings
|
||||
{
|
||||
/// <summary>
|
||||
/// Base class for all settings ScriptableObjects.
|
||||
/// Provides common functionality for all settings types.
|
||||
/// </summary>
|
||||
public abstract class BaseSettings : ScriptableObject
|
||||
{
|
||||
public virtual void OnValidate()
|
||||
{
|
||||
// Override in derived classes to add validation
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Core/Settings/BaseSettings.cs.meta
Normal file
3
Assets/Scripts/Core/Settings/BaseSettings.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cd33ef6036eb49358acbbd50dfd9bb13
|
||||
timeCreated: 1758619858
|
||||
48
Assets/Scripts/Core/Settings/InteractionSettings.cs
Normal file
48
Assets/Scripts/Core/Settings/InteractionSettings.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AppleHills.Core.Settings
|
||||
{
|
||||
/// <summary>
|
||||
/// Settings related to interactions and items
|
||||
/// </summary>
|
||||
[CreateAssetMenu(fileName = "InteractionSettings", menuName = "AppleHills/Settings/Interaction & Items", order = 2)]
|
||||
public class InteractionSettings : BaseSettings, IInteractionSettings
|
||||
{
|
||||
[Header("Interactions")]
|
||||
[SerializeField] private float playerStopDistance = 6.0f;
|
||||
[SerializeField] private float playerStopDistanceDirectInteraction = 2.0f;
|
||||
[SerializeField] private float followerPickupDelay = 0.2f;
|
||||
|
||||
[Header("InputManager Settings")]
|
||||
[Tooltip("Layer(s) to use for interactable objects.")]
|
||||
[SerializeField] private LayerMask interactableLayerMask = -1; // Default to Everything
|
||||
|
||||
[Header("Default Prefabs")]
|
||||
[SerializeField] private GameObject basePickupPrefab;
|
||||
[SerializeField] private GameObject levelSwitchMenuPrefab;
|
||||
|
||||
[Header("Item Configuration")]
|
||||
[SerializeField] private List<GameSettings.CombinationRule> combinationRules = new List<GameSettings.CombinationRule>();
|
||||
[SerializeField] private List<GameSettings.SlotItemConfig> slotItemConfigs = new List<GameSettings.SlotItemConfig>();
|
||||
|
||||
// IInteractionSettings implementation
|
||||
public float PlayerStopDistance => playerStopDistance;
|
||||
public float PlayerStopDistanceDirectInteraction => playerStopDistanceDirectInteraction;
|
||||
public float FollowerPickupDelay => followerPickupDelay;
|
||||
public LayerMask InteractableLayerMask => interactableLayerMask;
|
||||
public GameObject BasePickupPrefab => basePickupPrefab;
|
||||
public GameObject LevelSwitchMenuPrefab => levelSwitchMenuPrefab;
|
||||
public List<GameSettings.CombinationRule> CombinationRules => combinationRules;
|
||||
public List<GameSettings.SlotItemConfig> SlotItemConfigs => slotItemConfigs;
|
||||
|
||||
public override void OnValidate()
|
||||
{
|
||||
base.OnValidate();
|
||||
// Validate values
|
||||
playerStopDistance = Mathf.Max(0.1f, playerStopDistance);
|
||||
playerStopDistanceDirectInteraction = Mathf.Max(0.1f, playerStopDistanceDirectInteraction);
|
||||
followerPickupDelay = Mathf.Max(0f, followerPickupDelay);
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Core/Settings/InteractionSettings.cs.meta
Normal file
3
Assets/Scripts/Core/Settings/InteractionSettings.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ac22b092dc6f4db5b3dad35172b6e4c4
|
||||
timeCreated: 1758619914
|
||||
49
Assets/Scripts/Core/Settings/MinigameSettings.cs
Normal file
49
Assets/Scripts/Core/Settings/MinigameSettings.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace AppleHills.Core.Settings
|
||||
{
|
||||
/// <summary>
|
||||
/// Settings related to minigames
|
||||
/// </summary>
|
||||
[CreateAssetMenu(fileName = "MinigameSettings", menuName = "AppleHills/Settings/Minigames", order = 3)]
|
||||
public class MinigameSettings : BaseSettings, IMinigameSettings
|
||||
{
|
||||
[Header("Endless Descender Settings")]
|
||||
[Tooltip("How quickly the character follows the finger horizontally (higher = more responsive)")]
|
||||
[SerializeField] private float endlessDescenderLerpSpeed = 12f;
|
||||
|
||||
[Tooltip("Maximum horizontal offset allowed between character and finger position")]
|
||||
[SerializeField] private float endlessDescenderMaxOffset = 3f;
|
||||
|
||||
[Tooltip("Minimum allowed X position for endless descender movement")]
|
||||
[SerializeField] private float endlessDescenderClampXMin = -3.5f;
|
||||
|
||||
[Tooltip("Maximum allowed X position for endless descender movement")]
|
||||
[SerializeField] private float endlessDescenderClampXMax = 3.5f;
|
||||
|
||||
[Tooltip("Exponent for speed drop-off curve (higher = sharper drop near target)")]
|
||||
[SerializeField] private float endlessDescenderSpeedExponent = 2.5f;
|
||||
|
||||
// IMinigameSettings implementation
|
||||
public float EndlessDescenderLerpSpeed => endlessDescenderLerpSpeed;
|
||||
public float EndlessDescenderMaxOffset => endlessDescenderMaxOffset;
|
||||
public float EndlessDescenderClampXMin => endlessDescenderClampXMin;
|
||||
public float EndlessDescenderClampXMax => endlessDescenderClampXMax;
|
||||
public float EndlessDescenderSpeedExponent => endlessDescenderSpeedExponent;
|
||||
|
||||
public override void OnValidate()
|
||||
{
|
||||
base.OnValidate();
|
||||
// Validate values
|
||||
endlessDescenderLerpSpeed = Mathf.Max(0.1f, endlessDescenderLerpSpeed);
|
||||
endlessDescenderMaxOffset = Mathf.Max(0.1f, endlessDescenderMaxOffset);
|
||||
endlessDescenderSpeedExponent = Mathf.Max(0.1f, endlessDescenderSpeedExponent);
|
||||
|
||||
// Ensure min is less than max
|
||||
if (endlessDescenderClampXMin >= endlessDescenderClampXMax)
|
||||
{
|
||||
endlessDescenderClampXMin = endlessDescenderClampXMax - 0.1f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Core/Settings/MinigameSettings.cs.meta
Normal file
3
Assets/Scripts/Core/Settings/MinigameSettings.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0ce4dba7a1c54e73b1b3d7131a1c0570
|
||||
timeCreated: 1758619927
|
||||
53
Assets/Scripts/Core/Settings/PlayerFollowerSettings.cs
Normal file
53
Assets/Scripts/Core/Settings/PlayerFollowerSettings.cs
Normal file
@@ -0,0 +1,53 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace AppleHills.Core.Settings
|
||||
{
|
||||
/// <summary>
|
||||
/// Settings related to player and follower behavior
|
||||
/// </summary>
|
||||
[CreateAssetMenu(fileName = "PlayerFollowerSettings", menuName = "AppleHills/Settings/Player & Follower", order = 1)]
|
||||
public class PlayerFollowerSettings : BaseSettings, IPlayerFollowerSettings
|
||||
{
|
||||
[Header("Player Settings")]
|
||||
[SerializeField] private float moveSpeed = 5f;
|
||||
[SerializeField] private float stopDistance = 0.1f;
|
||||
[SerializeField] private bool useRigidbody = true;
|
||||
[SerializeField] private GameSettings.HoldMovementMode defaultHoldMovementMode = GameSettings.HoldMovementMode.Pathfinding;
|
||||
|
||||
[Header("Follower Settings")]
|
||||
[SerializeField] private float followDistance = 1.5f;
|
||||
[SerializeField] private float manualMoveSmooth = 8f;
|
||||
[SerializeField] private float thresholdFar = 2.5f;
|
||||
[SerializeField] private float thresholdNear = 0.5f;
|
||||
[SerializeField] private float stopThreshold = 0.1f;
|
||||
|
||||
[Header("Backend Settings")]
|
||||
[Tooltip("Technical parameters, not for design tuning")]
|
||||
[SerializeField] private float followUpdateInterval = 0.1f;
|
||||
[SerializeField] private float followerSpeedMultiplier = 1.2f;
|
||||
[SerializeField] private float heldIconDisplayHeight = 2.0f;
|
||||
|
||||
// IPlayerFollowerSettings implementation
|
||||
public float MoveSpeed => moveSpeed;
|
||||
public float StopDistance => stopDistance;
|
||||
public bool UseRigidbody => useRigidbody;
|
||||
public GameSettings.HoldMovementMode DefaultHoldMovementMode => defaultHoldMovementMode;
|
||||
public float FollowDistance => followDistance;
|
||||
public float ManualMoveSmooth => manualMoveSmooth;
|
||||
public float ThresholdFar => thresholdFar;
|
||||
public float ThresholdNear => thresholdNear;
|
||||
public float StopThreshold => stopThreshold;
|
||||
public float FollowUpdateInterval => followUpdateInterval;
|
||||
public float FollowerSpeedMultiplier => followerSpeedMultiplier;
|
||||
public float HeldIconDisplayHeight => heldIconDisplayHeight;
|
||||
|
||||
public override void OnValidate()
|
||||
{
|
||||
base.OnValidate();
|
||||
// Validate values
|
||||
moveSpeed = Mathf.Max(0.1f, moveSpeed);
|
||||
followDistance = Mathf.Max(0.1f, followDistance);
|
||||
followerSpeedMultiplier = Mathf.Max(0.1f, followerSpeedMultiplier);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 32cd6d14d9304d5ba0fd590da1346654
|
||||
timeCreated: 1758619904
|
||||
51
Assets/Scripts/Core/Settings/ServiceLocator.cs
Normal file
51
Assets/Scripts/Core/Settings/ServiceLocator.cs
Normal file
@@ -0,0 +1,51 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AppleHills.Core.Settings
|
||||
{
|
||||
/// <summary>
|
||||
/// Service Locator implementation for managing settings services.
|
||||
/// Provides a central registry for all settings services.
|
||||
/// </summary>
|
||||
public static class ServiceLocator
|
||||
{
|
||||
private static readonly Dictionary<Type, object> _services = new Dictionary<Type, object>();
|
||||
|
||||
/// <summary>
|
||||
/// Register a service with the service locator.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The interface type for the service</typeparam>
|
||||
/// <param name="service">The service implementation</param>
|
||||
public static void Register<T>(T service) where T : class
|
||||
{
|
||||
_services[typeof(T)] = service;
|
||||
Debug.Log($"Service registered: {typeof(T).Name}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a service from the service locator.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The interface type for the service</typeparam>
|
||||
/// <returns>The service implementation, or null if not found</returns>
|
||||
public static T Get<T>() where T : class
|
||||
{
|
||||
if (_services.TryGetValue(typeof(T), out object service))
|
||||
{
|
||||
return service as T;
|
||||
}
|
||||
|
||||
Debug.LogWarning($"Service of type {typeof(T).Name} not found!");
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clear all registered services.
|
||||
/// </summary>
|
||||
public static void Clear()
|
||||
{
|
||||
_services.Clear();
|
||||
Debug.Log("All services cleared");
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Core/Settings/ServiceLocator.cs.meta
Normal file
3
Assets/Scripts/Core/Settings/ServiceLocator.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 16cc39d2f99b4e7fa65c4a8b39f3e87c
|
||||
timeCreated: 1758619866
|
||||
54
Assets/Scripts/Core/Settings/SettingsInterfaces.cs
Normal file
54
Assets/Scripts/Core/Settings/SettingsInterfaces.cs
Normal file
@@ -0,0 +1,54 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace AppleHills.Core.Settings
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface for player and follower settings
|
||||
/// </summary>
|
||||
public interface IPlayerFollowerSettings
|
||||
{
|
||||
// Player settings
|
||||
float MoveSpeed { get; }
|
||||
float StopDistance { get; }
|
||||
bool UseRigidbody { get; }
|
||||
GameSettings.HoldMovementMode DefaultHoldMovementMode { get; }
|
||||
|
||||
// Follower settings
|
||||
float FollowDistance { get; }
|
||||
float ManualMoveSmooth { get; }
|
||||
float ThresholdFar { get; }
|
||||
float ThresholdNear { get; }
|
||||
float StopThreshold { get; }
|
||||
float FollowUpdateInterval { get; }
|
||||
float FollowerSpeedMultiplier { get; }
|
||||
float HeldIconDisplayHeight { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Interface for interaction and item settings
|
||||
/// </summary>
|
||||
public interface IInteractionSettings
|
||||
{
|
||||
float PlayerStopDistance { get; }
|
||||
float PlayerStopDistanceDirectInteraction { get; }
|
||||
float FollowerPickupDelay { get; }
|
||||
LayerMask InteractableLayerMask { get; }
|
||||
GameObject BasePickupPrefab { get; }
|
||||
GameObject LevelSwitchMenuPrefab { get; }
|
||||
System.Collections.Generic.List<GameSettings.CombinationRule> CombinationRules { get; }
|
||||
System.Collections.Generic.List<GameSettings.SlotItemConfig> SlotItemConfigs { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Interface for minigame settings
|
||||
/// </summary>
|
||||
public interface IMinigameSettings
|
||||
{
|
||||
// Endless Descender settings
|
||||
float EndlessDescenderLerpSpeed { get; }
|
||||
float EndlessDescenderMaxOffset { get; }
|
||||
float EndlessDescenderClampXMin { get; }
|
||||
float EndlessDescenderClampXMax { get; }
|
||||
float EndlessDescenderSpeedExponent { get; }
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Core/Settings/SettingsInterfaces.cs.meta
Normal file
3
Assets/Scripts/Core/Settings/SettingsInterfaces.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 54611ae012ab4455a53bd60961d9e7ea
|
||||
timeCreated: 1758619892
|
||||
106
Assets/Scripts/Core/Settings/SettingsProvider.cs
Normal file
106
Assets/Scripts/Core/Settings/SettingsProvider.cs
Normal file
@@ -0,0 +1,106 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.AddressableAssets;
|
||||
using UnityEngine.ResourceManagement.AsyncOperations;
|
||||
|
||||
namespace AppleHills.Core.Settings
|
||||
{
|
||||
/// <summary>
|
||||
/// Responsible for loading and caching settings from Addressables.
|
||||
/// </summary>
|
||||
public class SettingsProvider : MonoBehaviour
|
||||
{
|
||||
private static SettingsProvider _instance;
|
||||
private Dictionary<string, BaseSettings> _settingsCache = new Dictionary<string, BaseSettings>();
|
||||
|
||||
// Singleton instance
|
||||
public static SettingsProvider Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_instance == null)
|
||||
{
|
||||
GameObject go = new GameObject("Settings Provider");
|
||||
_instance = go.AddComponent<SettingsProvider>();
|
||||
DontDestroyOnLoad(go);
|
||||
}
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
if (_instance == null)
|
||||
{
|
||||
_instance = this;
|
||||
DontDestroyOnLoad(gameObject);
|
||||
}
|
||||
else if (_instance != this)
|
||||
{
|
||||
Destroy(gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Load settings asynchronously using Addressables
|
||||
/// </summary>
|
||||
public void LoadSettings<T>(Action<T> onLoaded) where T : BaseSettings
|
||||
{
|
||||
string key = typeof(T).Name;
|
||||
|
||||
// Return from cache if already loaded
|
||||
if (_settingsCache.TryGetValue(key, out BaseSettings cachedSettings))
|
||||
{
|
||||
onLoaded?.Invoke(cachedSettings as T);
|
||||
return;
|
||||
}
|
||||
|
||||
// Load using Addressables
|
||||
Addressables.LoadAssetAsync<T>($"Settings/{key}.asset").Completed += handle =>
|
||||
{
|
||||
if (handle.Status == AsyncOperationStatus.Succeeded)
|
||||
{
|
||||
_settingsCache[key] = handle.Result;
|
||||
onLoaded?.Invoke(handle.Result);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError($"Failed to load settings: {key}");
|
||||
onLoaded?.Invoke(null);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get cached settings
|
||||
/// </summary>
|
||||
public T GetSettings<T>() where T : BaseSettings
|
||||
{
|
||||
string key = typeof(T).Name;
|
||||
if (_settingsCache.TryGetValue(key, out BaseSettings settings))
|
||||
{
|
||||
return settings as T;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Preload all settings - call this at game startup
|
||||
/// </summary>
|
||||
public void PreloadAllSettings(Action onComplete)
|
||||
{
|
||||
// Load all necessary settings types
|
||||
int pendingLoads = 3; // Number of settings types
|
||||
Action decrementCounter = () => {
|
||||
pendingLoads--;
|
||||
if (pendingLoads <= 0)
|
||||
onComplete?.Invoke();
|
||||
};
|
||||
|
||||
LoadSettings<PlayerFollowerSettings>(settings => decrementCounter());
|
||||
LoadSettings<InteractionSettings>(settings => decrementCounter());
|
||||
LoadSettings<MinigameSettings>(settings => decrementCounter());
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Core/Settings/SettingsProvider.cs.meta
Normal file
3
Assets/Scripts/Core/Settings/SettingsProvider.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4d212b25192045d198f2bf42ef74f278
|
||||
timeCreated: 1758619879
|
||||
Reference in New Issue
Block a user