Working synchronous Addressables settings loading

This commit is contained in:
Michal Pikulski
2025-09-23 15:30:21 +02:00
parent 197aedddb0
commit 404f6f4e5c
4 changed files with 97 additions and 75 deletions

View File

@@ -1,6 +1,6 @@
using UnityEngine;
using AppleHills.Core.Settings;
using System.Collections;
using System;
/// <summary>
/// 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<GameSettings>("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<PlayerFollowerSettings>();
var interactionSettings = SettingsProvider.Instance.LoadSettingsSynchronous<InteractionSettings>();
var minigameSettings = SettingsProvider.Instance.LoadSettingsSynchronous<MinigameSettings>();
// Wait for settings to be loaded
while (!initComplete)
{
yield return null;
}
// Register settings with service locator
ServiceLocator.Register<IPlayerFollowerSettings>(
SettingsProvider.Instance.GetSettings<PlayerFollowerSettings>());
if (playerSettings != null)
{
ServiceLocator.Register<IPlayerFollowerSettings>(playerSettings);
Debug.Log("PlayerFollowerSettings registered successfully");
}
else
{
Debug.LogError("Failed to load PlayerFollowerSettings");
}
ServiceLocator.Register<IInteractionSettings>(
SettingsProvider.Instance.GetSettings<InteractionSettings>());
if (interactionSettings != null)
{
ServiceLocator.Register<IInteractionSettings>(interactionSettings);
Debug.Log("InteractionSettings registered successfully");
}
else
{
Debug.LogError("Failed to load InteractionSettings");
}
ServiceLocator.Register<IMinigameSettings>(
SettingsProvider.Instance.GetSettings<MinigameSettings>());
if (minigameSettings != null)
{
ServiceLocator.Register<IMinigameSettings>(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()
{

View File

@@ -8,6 +8,7 @@ namespace AppleHills.Core.Settings
{
/// <summary>
/// Responsible for loading and caching settings from Addressables.
/// Uses synchronous loading to ensure settings are available immediately.
/// </summary>
public class SettingsProvider : MonoBehaviour
{
@@ -43,64 +44,57 @@ namespace AppleHills.Core.Settings
}
/// <summary>
/// Load settings asynchronously using Addressables
/// Load settings synchronously using Addressables - blocks until complete
/// </summary>
public void LoadSettings<T>(Action<T> onLoaded) where T : BaseSettings
public T LoadSettingsSynchronous<T>() 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<T>($"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<T>($"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);
}
};
}
/// <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;
}
catch (Exception e)
{
Debug.LogError($"Error loading settings {key}: {e.Message}");
}
return null;
}
/// <summary>
/// Preload all settings - call this at game startup
/// Get cached settings or load them synchronously if not cached
/// </summary>
public void PreloadAllSettings(Action onComplete)
public T GetSettings<T>() 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<PlayerFollowerSettings>(settings => decrementCounter());
LoadSettings<InteractionSettings>(settings => decrementCounter());
LoadSettings<MinigameSettings>(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<T>();
}
}
}