194 lines
5.7 KiB
C#
194 lines
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;
|
|||
|
|
}
|