194 lines
No EOL
5.7 KiB
C#
194 lines
No EOL
5.7 KiB
C#
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<LevelExceptionSetup> _levelExceptions = new List<LevelExceptionSetup>();
|
||
[Tooltip("Группы сцен (например, для Меню или Магазинов)")]
|
||
[SerializeField] private List<LevelGroupSetup> _levelGroups = new List<LevelGroupSetup>();
|
||
[Tooltip("Настройки диапазонов с учетом префиксов")]
|
||
[SerializeField] private List<LevelRangeSetup> _levelRanges = new List<LevelRangeSetup>();
|
||
|
||
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<LevelImport>();
|
||
List<GameObject> blocks = new List<GameObject>();
|
||
|
||
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<GameObject>());
|
||
}
|
||
|
||
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<GameObject> 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<Image>();
|
||
}
|
||
}
|
||
|
||
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<List<GameObject>> 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;
|
||
} |