using System.Collections.Generic; using UnityEngine; public class NoiseManager : MonoBehaviour { [System.Serializable] public class NoiseEvent { public Vector3 position; public float intensity; public float timestamp; } public float noiseLifetime = 1.25f; public static NoiseManager Instance { get; private set; } public static IReadOnlyList ActiveNoises => activeNoises; private static readonly List activeNoises = new List(); private void Awake() { if (Instance != null && Instance != this) { Destroy(gameObject); return; } Instance = this; } private void Update() { PruneExpiredNoise(); } public static void EmitNoise(Vector3 position, float intensity) { EnsureInstance(); PruneExpiredNoise(); // Шум живёт короткое время, чтобы враги реагировали на свежие события, а не на старые следы. activeNoises.Add(new NoiseEvent { position = position, intensity = intensity, timestamp = Time.time }); } public static NoiseEvent GetClosestNoise(Vector3 listenerPosition, float hearingRange) { PruneExpiredNoise(); NoiseEvent closest = null; float closestDistance = float.MaxValue; for (int i = 0; i < activeNoises.Count; i++) { NoiseEvent noise = activeNoises[i]; float effectiveRange = Mathf.Max(0.1f, hearingRange * noise.intensity); float distance = Vector3.Distance(listenerPosition, noise.position); if (distance > effectiveRange || distance >= closestDistance) { continue; } closest = noise; closestDistance = distance; } return closest; } public static void ClearNoise() { activeNoises.Clear(); } private static void EnsureInstance() { if (Instance != null || !Application.isPlaying) { return; } GameObject managerObject = new GameObject("NoiseManager"); Instance = managerObject.AddComponent(); } private static void PruneExpiredNoise() { float lifetime = Instance != null ? Instance.noiseLifetime : 1.25f; float minTimestamp = Time.time - lifetime; for (int i = activeNoises.Count - 1; i >= 0; i--) { if (activeNoises[i].timestamp < minTimestamp) { activeNoises.RemoveAt(i); } } } }