using System.Collections.Generic; using System.Collections; using RR.Common.Settings; using UnityEngine; namespace RR.Game2D.Behaviour { [DisallowMultipleComponent] public sealed class EntitySpawnerManager : MonoBehaviour { [Header("Spawners")] [SerializeField] private EntitySpawner[] spawners; [SerializeField] private bool includeChildren = true; [SerializeField] private bool includeInactiveChildren = true; [Header("Initialize Spawn")] [SerializeField] private bool spawnOnInitialize; [Tooltip("Если включено, процент спавна берётся из настройки gameplay.gameDifficulty.")] [SerializeField] private bool useSettings = true; [Range(0f, 100f)] [SerializeField] private float initializeSpawnPercent = 100f; private readonly List _resolvedSpawners = new(); private readonly HashSet _deduplicationSet = new(); private const string GameDifficultyKey = "gameplay.gameDifficulty"; private const float SettingsWaitTimeout = 2f; public int LastSpawnedCount { get; private set; } private void Start() { if (!spawnOnInitialize) return; StartCoroutine(InitializeSpawnRoutine()); } public void SpawnConfiguredPercent() { SpawnPercent(GetConfiguredSpawnPercent()); } public void SpawnPercent(int percent) { SpawnPercent((float)percent); } public void SpawnPercent(float percent) { LastSpawnedCount = SpawnInternal(percent); } public void StartAllSpawners() { ResolveSpawners(); for (int i = 0; i < _resolvedSpawners.Count; i++) { if (_resolvedSpawners[i] != null) _resolvedSpawners[i].StartSpawning(); } } public void StopAllSpawners() { ResolveSpawners(); for (int i = 0; i < _resolvedSpawners.Count; i++) { if (_resolvedSpawners[i] != null) _resolvedSpawners[i].StopSpawning(); } } public void ClearAllSpawned() { ResolveSpawners(); for (int i = 0; i < _resolvedSpawners.Count; i++) { if (_resolvedSpawners[i] != null) _resolvedSpawners[i].ClearSpawned(); } } private int SpawnInternal(float percent) { ResolveSpawners(); int totalSpawned = 0; for (int i = 0; i < _resolvedSpawners.Count; i++) { EntitySpawner spawner = _resolvedSpawners[i]; if (spawner == null) continue; totalSpawned += spawner.SpawnPercent(percent); } return totalSpawned; } private void ResolveSpawners() { _resolvedSpawners.Clear(); _deduplicationSet.Clear(); if (spawners != null) { for (int i = 0; i < spawners.Length; i++) TryAddSpawner(spawners[i]); } if (!includeChildren) return; EntitySpawner[] childSpawners = GetComponentsInChildren(includeInactiveChildren); for (int i = 0; i < childSpawners.Length; i++) TryAddSpawner(childSpawners[i]); } private void TryAddSpawner(EntitySpawner spawner) { if (spawner == null || !_deduplicationSet.Add(spawner)) return; _resolvedSpawners.Add(spawner); } private IEnumerator InitializeSpawnRoutine() { if (useSettings) { float elapsed = 0f; while (SettingsManager.Instance == null && elapsed < SettingsWaitTimeout) { elapsed += Time.unscaledDeltaTime; yield return null; } } float percent = GetConfiguredSpawnPercent(); Debug.Log($"[{nameof(EntitySpawnerManager)}] Initialize spawn percent = {percent}", this); SpawnPercent(percent); } private float GetConfiguredSpawnPercent() { if (!useSettings) return initializeSpawnPercent; SettingsManager settingsManager = SettingsManager.Instance; if (settingsManager == null) { Debug.LogWarning( $"[{nameof(EntitySpawnerManager)}] SettingsManager.Instance not found. Using max difficulty spawn percent.", this); return 100f; } int difficultyIndex = settingsManager.GetInt(GameDifficultyKey); float percent = difficultyIndex switch { 0 => 25f, 1 => 50f, 2 => 75f, 3 => 100f, _ => 100f }; Debug.Log( $"[{nameof(EntitySpawnerManager)}] Difficulty index '{difficultyIndex}' from '{GameDifficultyKey}' resolved to {percent}%.", this); return percent; } } }