Working synchronous Addressables settings loading
This commit is contained in:
@@ -10,7 +10,6 @@ namespace AppleHills.Editor
|
|||||||
public class SettingsMigrationWindow : EditorWindow
|
public class SettingsMigrationWindow : EditorWindow
|
||||||
{
|
{
|
||||||
private GameSettings legacySettings;
|
private GameSettings legacySettings;
|
||||||
private bool settingsFolderExists;
|
|
||||||
private bool addressablesInstalled;
|
private bool addressablesInstalled;
|
||||||
private AddressableAssetSettings addressableSettings;
|
private AddressableAssetSettings addressableSettings;
|
||||||
private AddressableAssetGroup settingsGroup;
|
private AddressableAssetGroup settingsGroup;
|
||||||
@@ -19,7 +18,7 @@ namespace AppleHills.Editor
|
|||||||
private Vector2 scrollPosition;
|
private Vector2 scrollPosition;
|
||||||
private bool migrationCompleted = false;
|
private bool migrationCompleted = false;
|
||||||
|
|
||||||
[MenuItem("AppleHills/Migrate Legacy Settings")]
|
[MenuItem("Tools/Migrate Legacy Settings")]
|
||||||
public static void ShowWindow()
|
public static void ShowWindow()
|
||||||
{
|
{
|
||||||
var window = GetWindow<SettingsMigrationWindow>("Settings Migration");
|
var window = GetWindow<SettingsMigrationWindow>("Settings Migration");
|
||||||
@@ -28,9 +27,6 @@ namespace AppleHills.Editor
|
|||||||
|
|
||||||
private void OnEnable()
|
private void OnEnable()
|
||||||
{
|
{
|
||||||
// Check if Settings folder exists
|
|
||||||
settingsFolderExists = AssetDatabase.IsValidFolder("Assets/Settings");
|
|
||||||
|
|
||||||
// Check if Addressables package is installed
|
// Check if Addressables package is installed
|
||||||
addressablesInstalled = AddressableAssetSettingsDefaultObject.SettingsExists;
|
addressablesInstalled = AddressableAssetSettingsDefaultObject.SettingsExists;
|
||||||
|
|
||||||
@@ -60,8 +56,7 @@ namespace AppleHills.Editor
|
|||||||
|
|
||||||
EditorGUILayout.HelpBox(
|
EditorGUILayout.HelpBox(
|
||||||
"This tool will migrate your legacy GameSettings to the new modular settings system. " +
|
"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, " +
|
"It will create new settings assets and mark them as Addressables for synchronous loading at runtime.",
|
||||||
"and copy values from your legacy settings.",
|
|
||||||
MessageType.Info);
|
MessageType.Info);
|
||||||
|
|
||||||
EditorGUILayout.Space(10);
|
EditorGUILayout.Space(10);
|
||||||
@@ -112,7 +107,8 @@ namespace AppleHills.Editor
|
|||||||
EditorGUILayout.LabelField("Migration completed successfully!", successStyle);
|
EditorGUILayout.LabelField("Migration completed successfully!", successStyle);
|
||||||
EditorGUILayout.HelpBox(
|
EditorGUILayout.HelpBox(
|
||||||
"The legacy settings have been migrated to the new system. " +
|
"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);
|
MessageType.Info);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,10 +118,9 @@ namespace AppleHills.Editor
|
|||||||
private void MigrateSettings()
|
private void MigrateSettings()
|
||||||
{
|
{
|
||||||
// Create Settings folder if it doesn't exist
|
// Create Settings folder if it doesn't exist
|
||||||
if (!settingsFolderExists)
|
if (!AssetDatabase.IsValidFolder("Assets/Settings"))
|
||||||
{
|
{
|
||||||
AssetDatabase.CreateFolder("Assets", "Settings");
|
AssetDatabase.CreateFolder("Assets", "Settings");
|
||||||
settingsFolderExists = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup Addressables group for settings
|
// Setup Addressables group for settings
|
||||||
@@ -159,7 +154,7 @@ namespace AppleHills.Editor
|
|||||||
var guid = AssetDatabase.AssetPathToGUID(assetPath);
|
var guid = AssetDatabase.AssetPathToGUID(assetPath);
|
||||||
var entry = addressableSettings.CreateOrMoveEntry(guid, settingsGroup);
|
var entry = addressableSettings.CreateOrMoveEntry(guid, settingsGroup);
|
||||||
|
|
||||||
// Set the address
|
// Set the address - use without .asset extension for cleaner addresses
|
||||||
entry.address = address;
|
entry.address = address;
|
||||||
|
|
||||||
Debug.Log($"Added {assetPath} to Addressables with address {address}");
|
Debug.Log($"Added {assetPath} to Addressables with address {address}");
|
||||||
|
|||||||
@@ -1979,6 +1979,10 @@ PrefabInstance:
|
|||||||
propertyPath: m_LocalEulerAnglesHint.z
|
propertyPath: m_LocalEulerAnglesHint.z
|
||||||
value: 0
|
value: 0
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 7852204877518954380, guid: 8ac0210dbf9d7754e9526d6d5c214f49, type: 3}
|
||||||
|
propertyPath: maxSpeed
|
||||||
|
value: 15
|
||||||
|
objectReference: {fileID: 0}
|
||||||
m_RemovedComponents: []
|
m_RemovedComponents: []
|
||||||
m_RemovedGameObjects: []
|
m_RemovedGameObjects: []
|
||||||
m_AddedGameObjects: []
|
m_AddedGameObjects: []
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using AppleHills.Core.Settings;
|
using AppleHills.Core.Settings;
|
||||||
using System.Collections;
|
using System;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Singleton manager for global game state and settings. Provides accessors for various gameplay parameters.
|
/// 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")]
|
[Header("Settings Status")]
|
||||||
[SerializeField] private bool _settingsLoaded = false;
|
[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()
|
void Awake()
|
||||||
{
|
{
|
||||||
_instance = this;
|
_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
|
// Create settings provider if it doesn't exist
|
||||||
SettingsProvider.Instance.gameObject.name = "Settings Provider";
|
SettingsProvider.Instance.gameObject.name = "Settings Provider";
|
||||||
|
|
||||||
// Load all settings
|
// Load all settings synchronously during Awake
|
||||||
StartCoroutine(InitializeSettings());
|
InitializeSettings();
|
||||||
|
|
||||||
// DontDestroyOnLoad(gameObject);
|
// DontDestroyOnLoad(gameObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerator InitializeSettings()
|
private void InitializeSettings()
|
||||||
{
|
{
|
||||||
// Initialize the settings provider
|
Debug.Log("Starting settings initialization...");
|
||||||
var initComplete = false;
|
|
||||||
SettingsProvider.Instance.PreloadAllSettings(() => initComplete = true);
|
// 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
|
// Register settings with service locator
|
||||||
ServiceLocator.Register<IPlayerFollowerSettings>(
|
if (playerSettings != null)
|
||||||
SettingsProvider.Instance.GetSettings<PlayerFollowerSettings>());
|
{
|
||||||
|
ServiceLocator.Register<IPlayerFollowerSettings>(playerSettings);
|
||||||
|
Debug.Log("PlayerFollowerSettings registered successfully");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.LogError("Failed to load PlayerFollowerSettings");
|
||||||
|
}
|
||||||
|
|
||||||
ServiceLocator.Register<IInteractionSettings>(
|
if (interactionSettings != null)
|
||||||
SettingsProvider.Instance.GetSettings<InteractionSettings>());
|
{
|
||||||
|
ServiceLocator.Register<IInteractionSettings>(interactionSettings);
|
||||||
|
Debug.Log("InteractionSettings registered successfully");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.LogError("Failed to load InteractionSettings");
|
||||||
|
}
|
||||||
|
|
||||||
ServiceLocator.Register<IMinigameSettings>(
|
if (minigameSettings != null)
|
||||||
SettingsProvider.Instance.GetSettings<MinigameSettings>());
|
{
|
||||||
|
ServiceLocator.Register<IMinigameSettings>(minigameSettings);
|
||||||
|
Debug.Log("MinigameSettings registered successfully");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.LogError("Failed to load MinigameSettings");
|
||||||
|
}
|
||||||
|
|
||||||
// Log success
|
// Log success
|
||||||
Debug.Log("All settings loaded and registered with ServiceLocator");
|
_settingsLoaded = playerSettings != null && interactionSettings != null && minigameSettings != null;
|
||||||
_settingsLoaded = true;
|
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
|
// 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()
|
void OnApplicationQuit()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ namespace AppleHills.Core.Settings
|
|||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Responsible for loading and caching settings from Addressables.
|
/// Responsible for loading and caching settings from Addressables.
|
||||||
|
/// Uses synchronous loading to ensure settings are available immediately.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class SettingsProvider : MonoBehaviour
|
public class SettingsProvider : MonoBehaviour
|
||||||
{
|
{
|
||||||
@@ -43,64 +44,57 @@ namespace AppleHills.Core.Settings
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Load settings asynchronously using Addressables
|
/// Load settings synchronously using Addressables - blocks until complete
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void LoadSettings<T>(Action<T> onLoaded) where T : BaseSettings
|
public T LoadSettingsSynchronous<T>() where T : BaseSettings
|
||||||
{
|
{
|
||||||
string key = typeof(T).Name;
|
string key = typeof(T).Name;
|
||||||
|
|
||||||
// Return from cache if already loaded
|
// Return from cache if already loaded
|
||||||
if (_settingsCache.TryGetValue(key, out BaseSettings cachedSettings))
|
if (_settingsCache.TryGetValue(key, out BaseSettings cachedSettings))
|
||||||
{
|
{
|
||||||
onLoaded?.Invoke(cachedSettings as T);
|
return cachedSettings as T;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load using Addressables
|
// Load using Addressables synchronously
|
||||||
Addressables.LoadAssetAsync<T>($"Settings/{key}.asset").Completed += handle =>
|
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;
|
_settingsCache[key] = settings;
|
||||||
onLoaded?.Invoke(handle.Result);
|
return settings;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.LogError($"Failed to load settings: {key}");
|
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;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Preload all settings - call this at game startup
|
/// Get cached settings or load them synchronously if not cached
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void PreloadAllSettings(Action onComplete)
|
public T GetSettings<T>() where T : BaseSettings
|
||||||
{
|
{
|
||||||
// Load all necessary settings types
|
string key = typeof(T).Name;
|
||||||
int pendingLoads = 3; // Number of settings types
|
|
||||||
Action decrementCounter = () => {
|
|
||||||
pendingLoads--;
|
|
||||||
if (pendingLoads <= 0)
|
|
||||||
onComplete?.Invoke();
|
|
||||||
};
|
|
||||||
|
|
||||||
LoadSettings<PlayerFollowerSettings>(settings => decrementCounter());
|
// Return from cache if already loaded
|
||||||
LoadSettings<InteractionSettings>(settings => decrementCounter());
|
if (_settingsCache.TryGetValue(key, out BaseSettings cachedSettings))
|
||||||
LoadSettings<MinigameSettings>(settings => decrementCounter());
|
{
|
||||||
|
return cachedSettings as T;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load synchronously if not in cache
|
||||||
|
return LoadSettingsSynchronous<T>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user