106 lines
2.7 KiB
C#
106 lines
2.7 KiB
C#
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<NoiseEvent> ActiveNoises => activeNoises;
|
|
|
|
private static readonly List<NoiseEvent> activeNoises = new List<NoiseEvent>();
|
|
|
|
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<NoiseManager>();
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
}
|