diff --git a/Assets/Editor/SettingsMigrationWindow.cs b/Assets/Editor/SettingsMigrationWindow.cs index e87124bf..ccac423d 100644 --- a/Assets/Editor/SettingsMigrationWindow.cs +++ b/Assets/Editor/SettingsMigrationWindow.cs @@ -10,7 +10,6 @@ namespace AppleHills.Editor public class SettingsMigrationWindow : EditorWindow { private GameSettings legacySettings; - private bool settingsFolderExists; private bool addressablesInstalled; private AddressableAssetSettings addressableSettings; private AddressableAssetGroup settingsGroup; @@ -19,7 +18,7 @@ namespace AppleHills.Editor private Vector2 scrollPosition; private bool migrationCompleted = false; - [MenuItem("AppleHills/Migrate Legacy Settings")] + [MenuItem("Tools/Migrate Legacy Settings")] public static void ShowWindow() { var window = GetWindow("Settings Migration"); @@ -28,9 +27,6 @@ namespace AppleHills.Editor private void OnEnable() { - // Check if Settings folder exists - settingsFolderExists = AssetDatabase.IsValidFolder("Assets/Settings"); - // Check if Addressables package is installed addressablesInstalled = AddressableAssetSettingsDefaultObject.SettingsExists; @@ -60,8 +56,7 @@ namespace AppleHills.Editor EditorGUILayout.HelpBox( "This tool will migrate your legacy GameSettings to the new modular settings system. " + - "It will create new settings assets in the Assets/Settings folder, mark them as Addressables, " + - "and copy values from your legacy settings.", + "It will create new settings assets and mark them as Addressables for synchronous loading at runtime.", MessageType.Info); EditorGUILayout.Space(10); @@ -112,7 +107,8 @@ namespace AppleHills.Editor EditorGUILayout.LabelField("Migration completed successfully!", successStyle); EditorGUILayout.HelpBox( "The legacy settings have been migrated to the new system. " + - "You can now access these settings through the AppleHills > Settings Editor menu.", + "You can now access these settings through the AppleHills > Settings Editor menu. " + + "Settings are marked as Addressables and will load synchronously at runtime.", MessageType.Info); } @@ -122,10 +118,9 @@ namespace AppleHills.Editor private void MigrateSettings() { // Create Settings folder if it doesn't exist - if (!settingsFolderExists) + if (!AssetDatabase.IsValidFolder("Assets/Settings")) { AssetDatabase.CreateFolder("Assets", "Settings"); - settingsFolderExists = true; } // Setup Addressables group for settings @@ -159,7 +154,7 @@ namespace AppleHills.Editor var guid = AssetDatabase.AssetPathToGUID(assetPath); var entry = addressableSettings.CreateOrMoveEntry(guid, settingsGroup); - // Set the address + // Set the address - use without .asset extension for cleaner addresses entry.address = address; Debug.Log($"Added {assetPath} to Addressables with address {address}"); diff --git a/Assets/Scenes/Levels/AppleHillsOverworld.unity b/Assets/Scenes/Levels/AppleHillsOverworld.unity index 03f05fa3..44747a0a 100644 --- a/Assets/Scenes/Levels/AppleHillsOverworld.unity +++ b/Assets/Scenes/Levels/AppleHillsOverworld.unity @@ -1979,6 +1979,10 @@ PrefabInstance: propertyPath: m_LocalEulerAnglesHint.z value: 0 objectReference: {fileID: 0} + - target: {fileID: 7852204877518954380, guid: 8ac0210dbf9d7754e9526d6d5c214f49, type: 3} + propertyPath: maxSpeed + value: 15 + objectReference: {fileID: 0} m_RemovedComponents: [] m_RemovedGameObjects: [] m_AddedGameObjects: [] diff --git a/Assets/Scripts/Core/GameManager.cs b/Assets/Scripts/Core/GameManager.cs index 40ce344d..59c2ff53 100644 --- a/Assets/Scripts/Core/GameManager.cs +++ b/Assets/Scripts/Core/GameManager.cs @@ -1,6 +1,6 @@ using UnityEngine; using AppleHills.Core.Settings; -using System.Collections; +using System; /// /// Singleton manager for global game state and settings. Provides accessors for various gameplay parameters. @@ -37,59 +37,88 @@ public class GameManager : MonoBehaviour [Header("Settings Status")] [SerializeField] private bool _settingsLoaded = false; + public bool SettingsLoaded => _settingsLoaded; + + // Use this for fallback values when settings aren't loaded yet + [Header("Fallback Settings")] + [SerializeField] private GameSettings fallbackSettings; void Awake() { _instance = this; + // If no fallback settings assigned, try to load them + if (fallbackSettings == null) + { + fallbackSettings = Resources.Load("DefaultSettings"); + } + // Create settings provider if it doesn't exist SettingsProvider.Instance.gameObject.name = "Settings Provider"; - // Load all settings - StartCoroutine(InitializeSettings()); + // Load all settings synchronously during Awake + InitializeSettings(); // DontDestroyOnLoad(gameObject); } - private IEnumerator InitializeSettings() + private void InitializeSettings() { - // Initialize the settings provider - var initComplete = false; - SettingsProvider.Instance.PreloadAllSettings(() => initComplete = true); + Debug.Log("Starting settings initialization..."); + + // Load settings synchronously + var playerSettings = SettingsProvider.Instance.LoadSettingsSynchronous(); + var interactionSettings = SettingsProvider.Instance.LoadSettingsSynchronous(); + var minigameSettings = SettingsProvider.Instance.LoadSettingsSynchronous(); - // Wait for settings to be loaded - while (!initComplete) - { - yield return null; - } - // Register settings with service locator - ServiceLocator.Register( - SettingsProvider.Instance.GetSettings()); + if (playerSettings != null) + { + ServiceLocator.Register(playerSettings); + Debug.Log("PlayerFollowerSettings registered successfully"); + } + else + { + Debug.LogError("Failed to load PlayerFollowerSettings"); + } - ServiceLocator.Register( - SettingsProvider.Instance.GetSettings()); + if (interactionSettings != null) + { + ServiceLocator.Register(interactionSettings); + Debug.Log("InteractionSettings registered successfully"); + } + else + { + Debug.LogError("Failed to load InteractionSettings"); + } - ServiceLocator.Register( - SettingsProvider.Instance.GetSettings()); + if (minigameSettings != null) + { + ServiceLocator.Register(minigameSettings); + Debug.Log("MinigameSettings registered successfully"); + } + else + { + Debug.LogError("Failed to load MinigameSettings"); + } // Log success - Debug.Log("All settings loaded and registered with ServiceLocator"); - _settingsLoaded = true; + _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"); + } // Migrate settings if needed - if (legacyGameSettings != null) + if (legacyGameSettings != null && !playerSettings && !interactionSettings && !minigameSettings) { - MigrateFromLegacySettings(); + Debug.LogWarning("Legacy settings detected but failed to load new settings. Consider running the migration tool."); } } - - 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() { diff --git a/Assets/Scripts/Core/Settings/SettingsProvider.cs b/Assets/Scripts/Core/Settings/SettingsProvider.cs index a0d44d76..9f9ac284 100644 --- a/Assets/Scripts/Core/Settings/SettingsProvider.cs +++ b/Assets/Scripts/Core/Settings/SettingsProvider.cs @@ -8,6 +8,7 @@ namespace AppleHills.Core.Settings { /// /// Responsible for loading and caching settings from Addressables. + /// Uses synchronous loading to ensure settings are available immediately. /// public class SettingsProvider : MonoBehaviour { @@ -43,64 +44,57 @@ namespace AppleHills.Core.Settings } /// - /// Load settings asynchronously using Addressables + /// Load settings synchronously using Addressables - blocks until complete /// - public void LoadSettings(Action onLoaded) where T : BaseSettings + public T LoadSettingsSynchronous() 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; + return cachedSettings as T; } - // Load using Addressables - Addressables.LoadAssetAsync($"Settings/{key}.asset").Completed += handle => + // Load using Addressables synchronously + try { - if (handle.Status == AsyncOperationStatus.Succeeded) + // WaitForCompletion blocks until the asset is loaded + T settings = Addressables.LoadAssetAsync($"Settings/{key}").WaitForCompletion(); + + if (settings != null) { - _settingsCache[key] = handle.Result; - onLoaded?.Invoke(handle.Result); + _settingsCache[key] = settings; + return settings; } else { Debug.LogError($"Failed to load settings: {key}"); - onLoaded?.Invoke(null); } - }; - } - - /// - /// Get cached settings - /// - public T GetSettings() where T : BaseSettings - { - string key = typeof(T).Name; - if (_settingsCache.TryGetValue(key, out BaseSettings settings)) - { - return settings as T; } + catch (Exception e) + { + Debug.LogError($"Error loading settings {key}: {e.Message}"); + } + return null; } /// - /// Preload all settings - call this at game startup + /// Get cached settings or load them synchronously if not cached /// - public void PreloadAllSettings(Action onComplete) + public T GetSettings() where T : BaseSettings { - // Load all necessary settings types - int pendingLoads = 3; // Number of settings types - Action decrementCounter = () => { - pendingLoads--; - if (pendingLoads <= 0) - onComplete?.Invoke(); - }; + string key = typeof(T).Name; - LoadSettings(settings => decrementCounter()); - LoadSettings(settings => decrementCounter()); - LoadSettings(settings => decrementCounter()); + // Return from cache if already loaded + if (_settingsCache.TryGetValue(key, out BaseSettings cachedSettings)) + { + return cachedSettings as T; + } + + // Load synchronously if not in cache + return LoadSettingsSynchronous(); } } }