using System; using System.Collections; // Обязательно добавляем для работы с корутинами using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using UnityEngine.SceneManagement; [AddComponentMenu("Level Management/Level Environment Manager")] public class LevelEnvironmentManager : MonoBehaviour { public static LevelEnvironmentManager Instance { get; private set; } [Header("Components")] [SerializeField] private Image _backgroundImage; [Header("Configuration")] [SerializeField] private LevelConfig _defaultConfig; [SerializeField] private List _levelExceptions = new List(); [Tooltip("Группы сцен (например, для Меню или Магазинов)")] [SerializeField] private List _levelGroups = new List(); [Tooltip("Настройки диапазонов с учетом префиксов")] [SerializeField] private List _levelRanges = new List(); private void Awake() { if (Instance == null) { Instance = this; DontDestroyOnLoad(gameObject); } else { Destroy(gameObject); } } private void OnEnable() { SceneManager.sceneLoaded += OnSceneLoaded; LevelImport.OnLevelLoaded += HandleLevelLoaded; } private void OnDisable() { SceneManager.sceneLoaded -= OnSceneLoaded; LevelImport.OnLevelLoaded -= HandleLevelLoaded; } private void OnSceneLoaded(Scene scene, LoadSceneMode mode) { if (scene.name == "ImportLeverl") return; StartCoroutine(HandleLevelLoadedRoutine(scene.name)); } private IEnumerator HandleLevelLoadedRoutine(string levelName) { // Магия здесь: ждем окончания текущего кадра. // Это гарантирует, что все Awake и Start на загруженной сцене завершились. yield return null; HandleLevelLoaded(levelName); } public void HandleLevelLoaded(string levelName) { if (Instance != this) return; // 1. Ищем LevelImport LevelImport levelImport = FindFirstObjectByType(); List blocks = new List(); if (levelImport != null && levelImport.Blocks != null) { blocks = levelImport.Blocks; } // 2. Определяем конфиг LevelConfig targetConfig = DetermineConfig(levelName); // 3. Применяем конфигурацию ApplyConfig(targetConfig, blocks); } public void ApplyOverrideConfig(LevelConfig manualConfig) { ApplyConfig(manualConfig, new List()); } private LevelConfig DetermineConfig(string levelName) { // Исключения foreach (var exception in _levelExceptions) { if (string.Equals(exception.LevelName, levelName, StringComparison.OrdinalIgnoreCase)) return exception.Config; } // Группы foreach (var group in _levelGroups) { if (group.SceneNames == null) continue; foreach (var name in group.SceneNames) { if (string.Equals(name.Trim(), levelName.Trim(), StringComparison.OrdinalIgnoreCase)) { return group.Config; } } } // Диапазоны foreach (var range in _levelRanges) { if (levelName.StartsWith(range.Prefix, StringComparison.OrdinalIgnoreCase)) { string numericPart = levelName.Substring(range.Prefix.Length); if (int.TryParse(numericPart, out int levelID)) { if (levelID >= range.StartLevel && levelID <= range.EndLevel) return range.Config; } } } // Дефолт return _defaultConfig; } private void ApplyConfig(LevelConfig config, List blocks) { if (config == null) return; if (GlobalMusicManager.Instance != null) { GlobalMusicManager.Instance.PlayMusic(config.BackgroundMusic); } else { Debug.LogWarning("GlobalMusicManager.Instance is null! Музыка не применена."); } // В Unity безопаснее проверять просто на null для уничтоженных объектов if (_backgroundImage == null) { GameObject bgObj = GameObject.FindWithTag("BG"); if (bgObj != null) { _backgroundImage = bgObj.GetComponent(); } } if (_backgroundImage != null && config.BackgroundImage != null) { _backgroundImage.sprite = config.BackgroundImage; } // Вызываем события config.OnLevelConfigApplied?.Invoke(blocks); } } [Serializable] public class LevelConfig { public AudioClip BackgroundMusic; public Sprite BackgroundImage; public UnityEngine.Events.UnityEvent> OnLevelConfigApplied; } [Serializable] public class LevelGroupSetup { public string GroupName; public string[] SceneNames; public LevelConfig Config; } [Serializable] public class LevelRangeSetup { public string Prefix = "Level"; public int StartLevel; public int EndLevel; public LevelConfig Config; } [Serializable] public class LevelExceptionSetup { public string LevelName; public LevelConfig Config; }